Я построил сервер OPC UA из примера OPCFoundation - https://github.com/OPCFoundation/UA-.NETStandard
Также скомпилировал свою собственную модель с помощью - https://github.com/Pro/UA-ModelCompiler/tree/eebf9988940a789a4f36cbef8c5bd6340f1b2f42
В примерах у них есть сгенерированные файлы в папках, а затем пользовательские классы для NodeManger, State и так далее.
Я успешно загрузил сгенерированный файл .uanodes с некоторыми примерами узлов в нем. Но я не могу создавать эти узлы с помощью кода со стороны сервера. При тестировании делаю это в функции - LoadPredefinedNodes (контекст ISystemContext).
Моя структура должна быть узлом под объектами под названием «Теги», в этом узле я хочу динамически добавлять узлы и устанавливать их свойства во время работы сервера.
При тестировании я использую клиент OPC UA объекта интеграции.
Структура выглядит правильно, например: Объекты => Теги => MyTestTag (Свойства: Имя, Описание, Значение)
Первые два свойства добавлены правильно из определения файла модели.
<!-- ### Object Types ###-->
<!-- BaseType -->
<ObjectType SymbolicName="TAG:TagType" BaseType="ua:BaseObjectType" IsAbstract="true" SupportsEvents="true" AccessLevel="ReadWrite">
<Description>Base type for all tags</Description>
<Children>
<Property SymbolicName="TAG:Name" DataType="ua:String" ValueRank="Scalar" ModellingRule="Mandatory" AccessLevel="ReadWrite">
<Description>Name of the tag</Description>
</Property>
<Property SymbolicName="TAG:Description" DataType="ua:String" ValueRank="Scalar" ModellingRule="Optional" AccessLevel="ReadWrite">
<Description>Description of the tag</Description>
</Property>
</Children>
</ObjectType>
<!-- ### Objects ###-->
<Object SymbolicName="TAG:Tags" TypeDefinition="ua:BaseObjectType">
<Description>Contains all instances of tags</Description>
<References>
<Reference IsInverse="true">
<ReferenceType>ua:Organizes</ReferenceType>
<TargetId>ua:ObjectsFolder</TargetId>
</Reference>
</References>
</Object>
Третий - это свойство, которое я пытаюсь определить из кода на стороне сервера. Я добавил свойство Value, но не могу понять, как записать его значение.
protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context)
{
NodeStateCollection predefinedNodes = new NodeStateCollection();
predefinedNodes.LoadFromBinaryResource(context, "Opc.Ua.ValmetData.Tag.Tag.PredefinedNodes.uanodes", this.GetType().GetTypeInfo().Assembly, true);
// The defined ObjectType in the model
NodeState tageTypeNode = predefinedNodes.Find(x => x.SymbolicName == "TagType");
// List node to add the tag to
NodeState tagsNode = predefinedNodes.Find(x => x.SymbolicName == "Tags");
ushort namespaceIndex = Server.NamespaceUris.GetIndexOrAppend(Namespaces.Tag);
TagState tagNode = new TagState(tagsNode);
tagNode.SymbolicName = "MyTestTag";
tagNode.ClearChangeMasks(context, true);
PropertyState ps = new PropertyState(tagNode);
ps.ClearChangeMasks(context, true);
ps.NodeId = new NodeId();
ps.Description = "This is a description";
ps.TypeDefinitionId = tageTypeNode.NodeId;
ps.NumericId = 66;
// ps.NodeClass = NodeClass.Variable;
ps.ReferenceTypeId = ReferenceTypeIds.HasProperty;
ps.BrowseName = new QualifiedName("Value", NamespaceIndex);
ps.DisplayName = ps.BrowseName.Name;
ps.DataType = (uint)BuiltInType.Int32;
// ps.UserAccessLevel = AccessLevels.CurrentReadOrWrite;
// ps.AccessLevel = AccessLevels.CurrentReadOrWrite;
ps.Value = 66;
tagNode.AddChild(ps);
// assign
tagNode.Create(
SystemContext,
new NodeId(tagNode.SymbolicName, namespaceIndex),
new QualifiedName(tagNode.SymbolicName, namespaceIndex),
null,
true);
tagsNode.AddChild(tagNode);
return predefinedNodes;
}
Из этого кода в узел Теги добавляется узел MyTestTag. Свойства «Имя» и «Описание» добавлены из модели. А свойство «Значение» добавляется кодом. Однако я не могу установить значение ни для одного из этих свойств.
При нажатии на свойство MyTestTag.Value в клиенте выводится ошибка «Обнуляемый объект должен иметь значение».
Подскажите пожалуйста, что я делаю не так.