You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OPC UA Foundation SDK .NET中OnSimpleWriteValue复杂数据返回byte[]问题

问题分析

在OPC UA服务器的OnSimpleWriteValue事件中,基础类型(int、float、string等)能正常读取,但处理实现IEncodable接口的复杂数据或其数组时,收到的是byte[]而非解码后的实体对象——当前解码逻辑未覆盖直接传入byte[]的场景,且解码方式存在错误。

解决方案

核心思路:先根据变量节点的DataType确定目标解码类型,再针对byte[]、ExtensionObject、ExtensionObject[]三种输入场景分别处理,确保正确解码为对应的实体类或数组。

修改后的关键代码

1. 修正OnPropertyChangedByOpc方法

private static ServiceResult OnPropertyChangedByOpc<P>(ISystemContext ctx, NodeState n, P property, object value)
    where P : PropertyChanged
{
    var variableState = n as BaseVariableState;
    if (variableState == null) return ServiceResult.BadNodeIdUnknown;

    // 从变量节点的DataType获取目标解码类型
    var dataTypeNodeId = variableState.DataType;
    var targetType = ctx.TypeTree.FindType(dataTypeNodeId);
    if (targetType == null) return ServiceResult.BadTypeDefinitionInvalid;

    object decodedValue = null;

    // 处理直接传入的byte[](复杂类型可能直接以二进制形式传递)
    if (value is byte[] rawBytes)
    {
        decodedValue = rawBytes.DecodeToType(targetType);
    }
    // 处理单个ExtensionObject
    else if (value is ExtensionObject extObj)
    {
        decodedValue = extObj.DecodeToType(targetType);
    }
    // 处理ExtensionObject数组(对应复杂类型数组)
    else if (value is ExtensionObject[] extArr)
    {
        var elementType = targetType.GetElementType();
        if (elementType == null) return ServiceResult.BadTypeMismatch;

        var decodedArray = Array.CreateInstance(elementType, extArr.Length);
        for (int i = 0; i < extArr.Length; i++)
        {
            decodedArray.SetValue(extArr[i].DecodeToType(elementType), i);
        }
        decodedValue = decodedArray;
    }
    // 基础类型直接使用
    else
    {
        decodedValue = value;
    }

    property.SetValue(decodedValue);
    return ServiceResult.Good;
}

2. 新增/修正解码扩展方法

private static object DecodeToType(this byte[] rawBytes, Type targetType)
{
    using var decoder = new BinaryDecoder(rawBytes, ServiceMessageContext.GlobalContext);
    // 直接解码到目标IEncodable类型,避免嵌套读取ExtensionObject的错误逻辑
    return decoder.ReadEncodeable(null, targetType);
}

private static object DecodeToType(this ExtensionObject extObj, Type targetType)
{
    if (extObj.Body is not byte[] bodyBytes) return null;
    return bodyBytes.DecodeToType(targetType);
}

关键说明

  • 类型匹配:通过变量节点的DataType属性获取目标类型,确保解码类型与节点定义严格一致,避免依赖泛型参数的局限性。
  • 全场景覆盖:处理了byte[]直接传入、单个ExtensionObject、ExtensionObject数组三种复杂类型写入的常见场景。
  • 解码逻辑修正:使用ReadEncodeable直接解码到目标IEncodable类型,替代原代码中嵌套读取ExtensionObject的错误逻辑。
  • 类型注册前提:确保你的IEncodable实体类已通过TypeTree.RegisterType或对应方式注册到OPC UA类型系统中,否则解码会失败。

内容的提问来源于stack exchange,提问作者Teo230

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:52:32