如何在C#的OPC UA服务器中创建可用的File对象?
解决OPC UA服务器中File对象无法正常工作的问题
你当前的代码仅创建了FileState的基础节点框架,但OPC UA的FileType需要绑定实际文件操作逻辑、初始化核心属性,否则会返回BadImplementation和BadAttributeIdInvalid错误。以下是需要补充的关键实现:
1. 初始化FileType的核心属性
FileState默认未设置Size、Writable、OpenCount等必填属性的取值或回调,客户端读取时会返回属性无效错误。需手动初始化这些属性:
// 初始化文件大小属性 file.Size = new PropertyState<long>(file) { Value = 0, AccessLevel = AccessLevels.CurrentRead, UserAccessLevel = AccessLevels.CurrentRead }; // 初始化可写状态属性 file.Writable = new PropertyState<bool>(file) { Value = true, AccessLevel = AccessLevels.CurrentRead, UserAccessLevel = AccessLevels.CurrentRead }; // 初始化打开计数属性 file.OpenCount = new PropertyState<ushort>(file) { Value = 0, AccessLevel = AccessLevels.CurrentRead, UserAccessLevel = AccessLevels.CurrentRead };
2. 实现文件操作的方法回调
OPC UA的FileType定义了Open/Close/Read/Write等方法,必须绑定实际文件操作逻辑才能让客户端正常交互:
绑定Open方法
file.OpenMethod = new MethodState(file) { OnCall = (context, inputArguments, outputArguments) => { // 替换为你的本地文件路径 Stream fileStream = new FileStream(@"C:\OPC_Files\FileName.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite); // 将文件流存入节点上下文,供后续读写使用 context.Node.SetContext(fileStream); // 更新打开计数 file.OpenCount.Value++; file.OpenCount.ClearChangeMasks(context, true); return StatusCodes.Good; } };
绑定Close方法
file.CloseMethod = new MethodState(file) { OnCall = (context, inputArguments, outputArguments) => { Stream fileStream = context.Node.GetContext<Stream>(); fileStream?.Close(); fileStream?.Dispose(); context.Node.SetContext(null); // 更新打开计数 file.OpenCount.Value--; file.OpenCount.ClearChangeMasks(context, true); return StatusCodes.Good; } };
绑定Read方法
file.ReadMethod = new MethodState(file) { OnCall = (context, inputArguments, outputArguments) => { Stream fileStream = context.Node.GetContext<Stream>(); if (fileStream == null) return StatusCodes.BadNotOpen; int readLength = (int)inputArguments[0]; byte[] buffer = new byte[readLength]; int actualRead = fileStream.Read(buffer, 0, readLength); outputArguments[0] = buffer.Take(actualRead).ToArray(); return StatusCodes.Good; } };
绑定Write方法
file.WriteMethod = new MethodState(file) { OnCall = (context, inputArguments, outputArguments) => { Stream fileStream = context.Node.GetContext<Stream>(); if (fileStream == null) return StatusCodes.BadNotOpen; byte[] writeData = (byte[])inputArguments[0]; fileStream.Write(writeData, 0, writeData.Length); // 更新文件大小属性 file.Size.Value = fileStream.Length; file.Size.ClearChangeMasks(context, true); return StatusCodes.Good; } };
3. 修正NodeId设置
你当前使用的ObjectIds.FileDirectoryType_FileName_Placeholder是标准占位符ID,需替换为自定义的唯一NodeId,避免冲突:
NodeId = new NodeId("Custom_FileName", NamespaceIndex), // 或使用GUID生成唯一ID:NodeId = new NodeId(Guid.NewGuid(), NamespaceIndex)
4. 配置正确的访问权限
确保节点权限允许客户端进行读写和方法调用:
file.RolePermissions = new List<RolePermissionType> { new RolePermissionType { RoleId = ObjectIds.Anonymous, Permissions = PermissionType.Read | PermissionType.Write | PermissionType.Call } };
内容的提问来源于stack exchange,提问作者Bruno Luís
相关产品推荐
相关产品推荐

