Обновление узлов OP C UA напрямую с сервера - PullRequest
0 голосов
/ 16 января 2020

Я новичок в разработке 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 , это выглядит мой первый подход, но он все еще не отвечает на мои вопросы.

...