Net8/Net10开源企业级跨平台数据采集系统,基于Avaloniaui

支持协议:

FinsTcp/S7/EtherNet/OPC UA/Secs/Gem/Modbus/WebSocket等,支持各类PLC

软件界面截图:动态多语言管理、菜单管理、数据源管理、对接表管理、软件版本号等

操作视频

软件功能

先上源码截图

在App.axaml.cs增加启动画面

cs 复制代码
 public override async void OnFrameworkInitializationCompleted()
 {
     if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
     {
         // 显示启动画面
         _splashScreen = new SplashScreen();
         _splashScreen.Show();
         await InitializeApplicationAsync();
         await Dispatcher.UIThread.InvokeAsync(() =>
         {
             var main = new MainWindow()
             {
                 DataContext = new MainWindowViewModel()
             };
             desktop.MainWindow = main;
             main.Show();
             _splashScreen.Close();
         });
     }
     base.OnFrameworkInitializationCompleted();
 }

OPC Server

cs 复制代码
 ApplicationInstance application = new ApplicationInstance();
 application.ConfigSectionName = "OpcUaServer";
 await application.LoadApplicationConfigurationAsync(false);
 await application.CheckApplicationInstanceCertificatesAsync(false, 0);

 var server = new StandardServer();
 var nodeManagerFactory = new NodeManagerFactory();
 server.AddNodeManager(nodeManagerFactory);
 await application.StartAsync(server);

OPC结构体解析

cs 复制代码
 /// <summary>
 /// 读取结构体
 /// </summary>
 public class StructureDto
 {
     public string Address { get; set; }
     public string Tag { get; set; }
     public StructureField StructureField { get; set; }
     public StructureDefinition StructureDefinition { get; set; }
     public BuiltInType BuiltInType { get; set; }
     public ExpandedNodeId TypeId { get; set; }
     public NodeId NodeId { get; set; }
 }

读取结构体

cs 复制代码
 /// <summary>
 /// 读取结构体
 /// </summary>
 /// <param name="address"></param>
 /// <param name="session"></param>
 /// <param name="opcNs"></param>
 /// <returns></returns>
 public static object ReadNoteStructure(string address, ISession session, string opcNs = null)
 {
     var arr = address.Split('.');
     if (arr.Length > 0)
     {
         if (opcNs == null)
         {
             opcNs = ns;
         }
         string tag = $"{opcNs};s={arr[0]}";
         var readDtReq = new ReadValueId
         {
             NodeId = tag,
             AttributeId = Attributes.DataType
         };
         var readReqs = new ReadValueIdCollection { readDtReq };
         session.Read(null, 0, TimestampsToReturn.Neither, readReqs, out DataValueCollection dtResults, out DiagnosticInfoCollection diag);
         var dataTypeId = dtResults[0].Value as NodeId;
         var readDefReq = new ReadValueId
         {
             NodeId = dataTypeId,
             AttributeId = Attributes.DataTypeDefinition
         };
         var readValue = new ReadValueId
         {
             NodeId = readDtReq.NodeId,
             AttributeId = Attributes.Value
         };
         session.Read(null, 0, TimestampsToReturn.Neither, new ReadValueIdCollection { readDefReq, readValue }, out DataValueCollection defResults, out DiagnosticInfoCollection diag2);
         ExtensionObject dataExt = null;
         if (defResults.Count >= 2)
         {
             dataExt = defResults[1].Value as ExtensionObject;
         }
         if (defResults[0].Value is ExtensionObject defExt)
         {
             if (defExt.Body is StructureDefinition structDef)
             {
                 if (!nodes.ContainsKey(tag))
                 {
                     nodes.Add(tag, structDef);
                 }
                 foreach (var field in structDef.Fields)
                 {
                     string key = $"{arr[0]}.{field.Name}";
                     if (!OpcStructureHelper.structDefCache.ContainsKey(key))
                     {
                         StructureDto structureDto = new StructureDto();
                         structureDto.Address = key;
                         structureDto.Tag = tag;
                         structureDto.StructureDefinition = structDef;
                         structureDto.StructureField = field;
                         structureDto.TypeId = dataExt.TypeId;
                         structureDto.NodeId = dataTypeId;
                         structureDto.BuiltInType = (BuiltInType)Convert.ToInt32(field.DataType.Identifier);
                         OpcStructureHelper.structDefCache.Add(key, structureDto);
                     }
                 }
             }
             if (defResults.Count >= 2 && dataExt != null)
             {
                 return dataExt.Body;
             }
         }
     }
     return null;
 }

写入结构体(无法真正写入结构体单个值,只能先读整体字节流,再改,再写入,达到修改目的)

cs 复制代码
public static bool WriteValue(string key, object value)
{
    object val = null;
    if (structDefCache.ContainsKey(key))
    {
        val = ReadValue(structDefCache[key].Tag);
    }
    else
    {
        val = ReadNoteStructure(key, session);
    }
    if (structDefCache.ContainsKey(key) && val != null)
    {
        if (val is byte[] dataValue)
        {
            var vals = DecodeWithStructure(session.MessageContext, structDefCache[key].StructureDefinition, dataValue);
            byte[] newRaw;
            using (var ms2 = new MemoryStream())
            {
                var encoder = new BinaryEncoder(ms2, session.MessageContext, true);
                var wkey = structDefCache[key].StructureField.Name;
                foreach (var item in vals)
                {
                    if (item.Key == wkey)
                    {
                        WriteBuiltinValue(structDefCache[key].StructureDefinition, encoder, item.Key, value);
                    }
                    else
                    {
                        WriteBuiltinValue(structDefCache[key].StructureDefinition, encoder, item.Key, item.Value);
                    }
                }
                encoder.Close();
                newRaw = ms2.ToArray();
            }
            var newExt = new ExtensionObject(structDefCache[key].TypeId, newRaw);

            var write = new WriteValue
            {
                NodeId = structDefCache[key].Tag,
                AttributeId = Attributes.Value,
                Value = new DataValue(new Variant(newExt))
            };
            session.Write(null, new WriteValueCollection { write }, out StatusCodeCollection results, out DiagnosticInfoCollection diag);
            if (StatusCode.IsGood(results[0]))
            {
                return true;
            }
        }

    }
    return false;
}
cs 复制代码
public static Dictionary<string, object> DecodeWithStructure(IServiceMessageContext context, StructureDefinition structDef, byte[] raw)
{
    var result = new Dictionary<string, object>();

    using (var ms = new MemoryStream(raw))
    {
        var decoder = new BinaryDecoder(ms, context);

        foreach (var field in structDef.Fields)
        {
            var value = DecodeField(field, decoder);
            result[field.Name] = value;
        }
    }
    return result;
}
cs 复制代码
private static object DecodeField(StructureField field, BinaryDecoder decoder)
{
    // 判断是否数组:ValueRank >= 0 表示数组 (ValueRank 可能为 ValueRanks.OneDimension = 1)
    bool isArray = field.ValueRank >= 0;

    // 判断是否内置类型(namespaceIndex == 0)
    bool isBuiltin = field.DataType != null && field.DataType.NamespaceIndex == 0;
    BuiltInType builtIn = BuiltInType.Null;
    if (isBuiltin)
    {
        builtIn = (BuiltInType)Convert.ToInt32(field.DataType.Identifier);
    }
    if (isArray)
    {
        // UA Binary 数组先编码为 Int32 长度(-1 表示 null)
        int length = decoder.ReadInt32(field.Name);
        if (length < 0) return null;

        var list = new List<object>(length);
        for (int i = 0; i < length; i++)
        {
            if (isBuiltin)
            {
                list.Add(ReadBuiltinValue(builtIn, decoder, field.Name));
            }
            else
            {
                // 自定义结构:数组元素以 ExtensionObject 形式编码
                // var xo = decoder.ReadExtensionObject(field.Name);
                //if (xo == null) list.Add(null);
                //else list.Add(DecodeExtensionObjectRecursive(xo));
            }
        }
        return list.ToArray(); // 或返回 List<object>,按需改
    }
    else
    {
        if (isBuiltin)
        {
            return ReadBuiltinValue(builtIn, decoder, field.Name);
        }
        else
        {
            // 自定义结构(标量)通常以 ExtensionObject 编码
            var xo = decoder.ReadExtensionObject(field.Name);
            return null;
        }
    }
}

PLC数据监控操作

1.下载对接表

2.修改IP地址,对接读写数据地址,PLC为取读地址,MES为写入地址

修改后,保存,再上传即可。

点"对接数据监控"即可查看PLC实时数据

下载链接

下载链接为编译后运行,只提供windows版本,源码获取在第三张截图里。

链接: https://pan.baidu.com/s/1TgdBTry5AhVsIDniL3ShfQ?pwd=r7xm 提取码: r7xm

相关推荐
莫生灬灬2 小时前
VueMultiBrowser - 开源多浏览器管理器
运维·开发语言·chrome·c#·自动化·vue
郝学胜-神的一滴2 小时前
Qt重复添加控件问题探析:现象、原理与解决方案
开发语言·数据库·c++·qt·程序人生
java porter2 小时前
系统架构设计之单例模式(下)
开发语言·javascript·单例模式
小北方城市网2 小时前
第 4 课:前端工程化进阶 ——Vue 核心语法 + 组件化开发(前端能力质的飞跃)
大数据·开发语言·数据库·python·状态模式·数据库架构
zhaokuner2 小时前
02-通用语言与协作-DDD领域驱动设计
java·开发语言·设计模式·架构
㳺三才人子2 小时前
初探 Python + Django
开发语言·python·django
嵌入式×边缘AI:打怪升级日志2 小时前
USB设备枚举过程详解:从插入到正常工作
开发语言·数据库·笔记
molaifeng2 小时前
深度解密 Go 语言调度器:GMP 模型精讲
开发语言·golang·gmp
资生算法程序员_畅想家_剑魔2 小时前
Java常见技术分享-27-事务安全-事务日志-事务日志框架
java·开发语言