Я новичок в разработке OP C UA и получил задание на разработку сервера OP C UA с использованием базового стека OP C UA и C#. Проблема заключается в том, что мы хотим иметь возможность доступа (чтения и обновления) к узлам внутри пространства имен не только с клиентов OP C UA, но и через внутренний поток, выполняющийся внутри серверного приложения. Это можно включить, сохранив указатель на узел во время настройки узла на сервере, т.е. CreateAddressSpace (унаследованный от CustomNodeManager2), как показано в приведенном ниже коде:
public override void CreateAddressSpace(IDictionary<NodeId, IList<IReference>> externalReferences)
{
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);
}
}
И затем достигните значения параметра внутри узел, для которого у меня пока есть два способа, описанных ниже: во-первых, просто обновив значение узла, перейдя непосредственно к переменной узла:
public void UpdateMystorage(int newValue)
{
// simply update the value field of the desired parameter:
myStorage.param1.Value += 1;
}
во-вторых, вызов метода записи, предоставляемого 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);
}
Мой первый вопрос: стоит ли обновлять узел напрямую из потока сервера? И в случае ДА, какой из перечисленных методов лучше? Последнее является более сложным, но у меня есть ощущение, что первый подход «может» вызвать некоторые проблемы параллелизма, если клиент должен получить данные одновременно.
PS: я также видел этот вопрос Как обновить узлы в OP C UA Server , это выглядит мой первый подход, но он все еще не отвечает на мои вопросы.