Updating the node directly from the server thread|OPC UA Implementation: Stacks, Tools, and Samples|Forum|OPC Foundation

Avatar
Search
Forum Scope


Match



Forum Options



Minimum search word length is 3 characters - maximum search word length is 84 characters
Lost password?
sp_Feed sp_PrintTopic sp_TopicIcon
Updating the node directly from the server thread
Avatar
Ramin Toussi
New Member
Members
Forum Posts: 2
Member Since:
10/01/2019
sp_UserOfflineSmall Offline
1
01/16/2020 - 07:33
sp_Permalink sp_Print

I am new to OPC UA development and have received a task to design an OPC UA server. The issue is that we want to be able to access (read and update) the nodes inside the namespace not only from the OPC UA clients but also through an internal thread running insider the server application. This can be enabled by keeping a pointer to the node during the node setup on the server, i.e. CreateAddressSpace (inherited from the CustomNodeManager2) like the code below shows:

public override void CreateAddressSpace(IDictionary<NodeId, IList<IReference>> externalReferences)
{
Dictionary<string, UNECEtoOPCUA> csvData = CreateUNECEtoOPCUADictionary();

lock (Lock)
{
LoadPredefinedNodes(SystemContext, externalReferences);

IList<IReference> references = null;
if (!externalReferences.TryGetValue(Opc.Ua.ObjectIds.ObjectsFolder, out references))
{
externalReferences[Opc.Ua.ObjectIds.ObjectsFolder] = references = new List<IReference>();
}

/*** Setup MyStorage node ***/
// This code is auto generated by the OPC UA model compiler
BaseObjectState passiveNode = (BaseObjectState)FindPredefinedNode(new NodeId(Objects.ExAct_TheStorage, NamespaceIndexes[0]), typeof(BaseObjectState));
myStorage = new MyStorageState(null); //variable declared as private
myStorage.Create(SystemContext, passiveNode);
Node_Setup.SetupMyStorageState.Setup(csvData, myStorage, SystemContext, NamespaceIndexes);
// Must do this AFTER any modifications to the node or its childnodes (especially if you're creating new instances (see InstrumentRange above)).
AddPredefinedNode(SystemContext, myStorage);
}
}

And then reach the parameter value inside the node for which I so far have two ways described below:
First, by simply updating the value of the node by going directly to node variable:

public void UpdateMystorage(int newValue)
{
// simply update the value field of the desired parameter:
myStorage.param1.Value += 1;
}

Second, calling the write method provided by the MasterNodeManager:

public void UpdateMystorage(int newValue)
{
WriteValue valueToWrite = new WriteValue();
valueToWrite.NodeId = myStorage.NodeId;
valueToWrite.AttributeId = Attributes.Value;
valueToWrite.Value.Value = newValue;
valueToWrite.Value.StatusCode = StatusCodes.Good;
valueToWrite.Value.ServerTimestamp = DateTime.MinValue;
valueToWrite.Value.SourceTimestamp = DateTime.MinValue;
var nodesToWrite = new WriteValueCollection();
nodesToWrite.Add(valueToWrite);

StatusCodeCollection results = null;
DiagnosticInfoCollection diagnosticInfos = null;
var operationContext = new Opc.Ua.Server.OperationContext(new RequestHeader(), Opc.Ua.Server.RequestType.Write);
server.masterNodeManager.Write(operationContext, nodesToWrite, out results, out diagnosticInfos);
}

My first question is if it is at all a good practice to update a node directly from the server thread?
And in case YES, which of the above methods is better? The latter is more complex but I have a feeling that the first approach "might" cause some concurrency issues if a client is to reach the data at the same time.

Avatar
Randy Armstrong
Admin
Forum Posts: 1451
Member Since:
05/30/2017
sp_UserOfflineSmall Offline
2
01/18/2020 - 05:33
sp_Permalink sp_Print

Look at the code in the base NodeManager class (CustomNodeManager).

See what locks are created. You must do the same.

Avatar
Ramin Toussi
New Member
Members
Forum Posts: 2
Member Since:
10/01/2019
sp_UserOfflineSmall Offline
3
01/20/2020 - 02:46
sp_Permalink sp_Print

Randy Armstrong said
Look at the code in the base NodeManager class (CustomNodeManager).

See what locks are created. You must do the same.

  

Thanks for the answer, using the following code should have the same effect:

server.masterNodeManager.Write(operationContext, nodesToWrite, out results, out diagnosticInfos);

ending up in proper locks.

I just thought it is better to use the already created lock instead of writing my own.

Forum Timezone: America/Phoenix
Most Users Ever Online: 510
Currently Online:
Guest(s) 18
Currently Browsing this Page:
1 Guest(s)
Top Posters:
Forum Stats:
Groups: 2
Forums: 10
Topics: 1349
Posts: 4577