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

Avalonia学习(二十三)-大屏 弄一个大屏显示的界面例子,但是代码有点多,还有用户控件。目前还有一点问题在解决,先看一下界面效果。 阅读详情

支持协议:

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

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

操作视频

软件功能

先上源码截图

在App.axaml.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

 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结构体解析

 /// <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; }
 }

读取结构体

 /// <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;
 }

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

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;
}
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;
}
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 

Avalonia学习(二十八)-OpenGL Avalonia已经继承了opengl,详细的大家可以自己查阅。Avalonia里面启用opengl继承OpenGlControlBase类就可以了。分别是初始化、绘制、释放。这里把官方源码的例子扒出来给大家看一下。源码在我以前发布的单组件里面。地址在前面的界面总结博文里面。 阅读详情

相关推荐

基于.NET的跨平台应用程序框架介绍

该文章对.NET跨平台应用程序框架进行了深入的评述。它介绍了.NET跨平台应用程序框架,并将其与其他应用程序框架(如Flutter、React Native或Ionic)进行了比较。文章还介绍了基于.NET的各种可用的跨平台应用程序框架,包括.NET MAUI、.NET MAUI Blazor混合、Avalonia UI、Uno平台和Xamarin。 此外,它解释了这些框架的使用和好处以及它们的比较,包括它们的架构。它得出的结论是,框架的选择在很大程度上取决于实际使用场景,因为所有框架都有其独特的优点和缺点

FinAnalyzer金融分析工具 1861

Avalonia学习实践(二)--跨平台支持及发布

Avalonia主打跨平台,号称一套代码支持Windows, macOS, Linux, iOS, Android操作系统,其基础是基于.NET Standard 2.0的一系列库,也就是只要平台能支持.NET Standard 2.0,就能运行Avalonia开发的应用。然而理想很丰满、显示很骨感,并不是说跨平台Avalonia没有做到,而是过程中免不了会有些小问题。 1.支持的平台 运行平台 版本 Windows Windows8及其以上版本(Window7也能用,但不保证没问题)

lordwish的专栏 1万+

VSCode + AvaloniaUI 跨平台开发环境搭建与 .NET 7 避坑指南

跨平台桌面应用开发中,UI 框架的渲染一致性与 IDE 的跨系统支持是关键。AvaloniaUI 基于 .NET 实现自绘渲染,不依赖系统原生控件,配合 XAML 可复用 WPF 经验,在 Windows、macOS 和 Linux 上提供一致的界面表现。VSCode 凭借轻量、三端体验统一和插件生态,成为跨平台开发的理想选择。本文围绕 .NET 7 环境配置、Avalonia 模板安装、调试设置及 XAML 预览等环节,梳理常见版本冲突与配置陷阱,帮助开发者快速搭建可落地的跨平台桌面开发工作流。

weixin_27791839的博客 229

行为模式——WPF和Avalonia中的视觉行为与实际示例

行为是一种相对较新的软件模式,允许非侵入性地修改对象的行为——无需修改对象的代码。WPF和Avalonia中使用的附加属性可用于在视觉对象上创建静态行为。本文展示了如何为视觉对象创建此类静态行为以及如何使用它们。

寒冰屋的专栏 2859

3天玩转C#与AvaloniaUI:跨平台桌面应用开发实战

桌面应用跨平台开发一直是技术选型中的难点,传统方案往往面临体积臃肿或重复开发的困境。C#作为成熟的.NET语言,结合AvaloniaUI这一新兴UI框架,提供了基于XAML的统一界面描述语言,并在GPU渲染管线的支撑下实现近原生性能。其MVVM架构模式与数据绑定机制,让开发者能够高效分离界面逻辑与业务逻辑。从环境搭建到布局设计,从样式动画到跨平台发布,这种组合尤其适合Windows、macOS、Linux三端复用的工程场景,也方便技术团队快速产出可演示的Demo。本文将梳理一套三天速成路径,分享在C#与Av

weixin_32642109的博客 253

基于.NET技术的Ant Design实现源码,AtomUI助力Avalonia/.NET跨平台桌面软件研发

该项目为基于.NET技术的Ant Design桌面软件实现源码,名为AtomUI,包含1452个文件,其中831个为SVG矢量图形,565个为C#源代码,18个为PNG图片,10个为.csproj项目文件,9个为属性文件,4个为Markdown文档,3个为批处理文件,3个为JSON配置文件,2个为XML文件,以及1个.gitignore忽略文件。AtomUI旨在将Ant Design的设计理念高效地应用于Avalonia/.NET跨平台桌面软件的开发中。

.Net Framework和.Net Core和.NET几个框架详细对比

.Net发展历程及平台对比

hssjf的专栏 1399

一个C#跨平台UI框架,支持Windows、Mac、Linux,支持国产Linux

C#跨平台UI框架,支持Windows、Mac、Linux,支持国产Linux

C# & AvaloniaUI 系列教程:第一课 - 开启跨平台 UI 开发之旅

摘要:本教程介绍了AvaloniaUI跨平台开发框架的入门指南。文章详细讲解了开发环境搭建步骤,包括Visual Studio 2025和.NET SDK的安装配置。通过创建第一个Avalonia项目,展示了项目结构和基本XAML控件使用。教程重点演示了MVVM模式实现,利用CommunityToolkit.Mvvm创建响应式界面,包括数据绑定和命令处理。最后通过"欢迎词生成器"实例,展示了文本框输入与按钮点击事件的完整交互流程,为初学者提供了完整的入门实践。

caifox的博客 5257

C# net上位机跨平台开发(Avalonia)

Avalonia框架采用Nuget安装,在GuGet包管理器中找到并安装avalonia扩展,安装完成后在创建新项目时会看到avalonia模块,选择该模块即可生成avalonia框架. AvaloniaDomo是Avalonia的源码,Avalonia的文件夹AvaloniaDomo作主框架功能块加入项目。 BLL和DAL是数据库模块,作为子项目的身份加入项目中。 使用“AvaloniaDomo”文件夹中的“AvaloniaDomo.sln”作为一个项目使用的示例。 该模块支持C#大部分程序框架,例如Console、winform、wpf、web等

Avalonia跨平台视频播放[项目源码]

本文介绍了如何使用.Net8 Avalonia跨平台UI框架中的vlc:VideoView控件播放海康监控和摄像机视频,支持Windows和Linux平台。文章详细说明了如何新建用户控件VideoViewControl.axaml,并引用VideoLAN.LibVLC.Windows包,以及在Linux平台上安装VLC和LibVLC的步骤。此外,还提供了.axaml和.axaml.cs的代码示例,展示了如何实现视频播放、错误处理和UI交互功能。最后,文章演示了如何在主页面MainWindow.axaml中使用该控件,并配置视频源和播放参数。

终极B站视频下载方案:跨平台开源工具完全指南

如何在多系统环境下高效下载B站内容?这是许多视频爱好者面临的共同挑战。今天我们将深入解析一款革命性的跨平台下载工具——哔哩下载姬,它不仅解决了平台兼容性问题,更提供了完整的免费B站下载解决方案。 ## 问题根源:为什么需要跨平台下载工具 随着内容消费习惯的变化,用户在不同设备间切换已成为常态。Windows用户有众多选择,但macOS和Linux用户往往难以找到合适的工具。哔哩下载姬的出现填补

gitblog_00874的博客 515

rk3326 MIPI休眠唤醒黑屏有背光问题

** 1.问题现象: ** **【开机起来】**开机起来可以正常显示 **【按power按键休眠】**第二次按下Power按键进入休眠,隔10s,再按Power按键唤醒。 **【出现结果】**屏幕黑屏有背光,并提示drm time out错 **【lcd信息】**lcd为480*800 2lane的mipi **【复现概率】**第二次按下休眠唤醒必然复现 【具体错误log如下】 //第一次休眠的log// [ 54.858511] dw-mipi-dsi ff450000.dsi: final DSI-

Ian22l的博客 3944

C#开源生态全景:核心框架与热门项目指南

开源生态是现代软件开发的重要基础设施,通过社区协作推动技术创新。C#作为微软主导的编程语言,自.NET Core开源后实现了真正的跨平台能力,其运行时支持Windows/Linux/macOS全平台,并原生集成容器化技术。在技术价值层面,开源C#项目显著降低了企业级应用的开发门槛,典型如ASP.NET Core构建高性能Web服务,ML.NET实现机器学习能力。当前热门应用场景覆盖Web开发、桌面应用、AI数据处理等领域,其中Dapper轻量级ORM和Serilog结构化日志等工具链项目已成为开发者标配。通

weixin_29574585的博客 272

【JESD79-5之】8 AC & DC 输入测量标准(AC & DC Input Measurement Levels)

时钟被驱动到DRAM,可以通过L/RDIMM模块的RCD来实现,也可以通过U/SODIMM模块的主机来实现(图184)。接收机DQS(脉冲)输入电压灵敏度测试提供了在没有码间干扰(ISI),抖动(Rj, Dj, DCD)和串扰噪声的情况下测试接收机对不同输入电压的灵敏度的方法。接收机数据输入电压灵敏度测试提供了在没有符号间干扰(ISI),抖动(Rj, Dj, DCD)和串扰噪声的情况下测试接收机对不同输入电压的灵敏度的方法。

m0_61126667的博客 1704

Android音频混音器AudioMixer实战:从多路输入到设备播放的完整流程解析

本文深入解析了Android平台上音频混音器AudioMixer的完整工作流程,涵盖从多路音频输入、轨道创建与配置、AudioBufferProvider数据源接入,到核心混音处理与最终设备播放的全过程。文章重点探讨了如何高效管理音频数据流、配置音量与重采样参数,并提供了缓冲区管理与性能优化的实战技巧,帮助开发者构建稳定、低延迟的音频应用。

l3m4n的博客 342

免费开源的B站视频下载工具怎么选:downkyicore跨平台版,8K下载与音视频分离一次说清

downkyicore(哔哩下载姬跨平台版)是一个基于 AvaloniaUI 框架开发的免费开源 B站视频下载工具,同时支持 Windows、Linux 和 macOS,能批量下载最高 8K、HDR 真彩、杜比视界的视频,并内置了音视频提取、去水印等实用工具箱。这篇文章不打算贴一堆源码,而是想用"为什么这样设计"的视角,把这个工具的工作原理和玩法讲明白。 ## 它为什么存在?一次被"平台"卡住的

gitblog_00654的博客 231

基础的pdf病毒木马

基础的pdf病毒木马 环境: 攻击机:Kali 目标操作系统:Windows 10或Windows 7 (关闭防火墙和安全软件) 目标软件:Adobe Reader 8.1.2 msf框架搜索:adobe-pdf 1.打开msfconsole 2.搜索 adobe_pdf模块 3.加载攻击模块并设置payload 4.运行生成pdf 5.将pdf拖入到win10 6.打开msf,加...

小小猪的博客 4623

.NET 8 + Avalonia 跨平台简易校园信息管理系统的开发实战

.NET 8 + Avalonia 跨平台简易校园信息管理系统的开发实战

寒冰屋的专栏 70

AI气象预报:数值模式融合与短临预警的工程实践

气象预报正经历从物理推演到数据驱动的认知范式转变。AI气象预报并非替代传统数值模式,而是通过数值模式融合弥补其在参数化误差、初值敏感性和计算效率上的固有瓶颈。其技术价值在于提升短临预警时效性与空间精度,支撑航空调度、电力调控、防洪应急等关键场景。实践中需兼顾物理一致性、可解释性与业务系统兼容性,避免纯黑箱建模带来的外推失效与不确定性缺失风险。本文聚焦AI作为超分辨率引擎、误差矫正器和短临加速器的三类落地路径,解析HEALPix投影、多尺度图建模、轻量级U-Net等核心适配方法。

weixin_28221501的博客 298

用 SAP ABAP ALV 重塑 SM30:可扩展的自定义表维护视图与自动传输实践

文章摘要: 本文提出了一种基于ALV Grid的动态表维护框架,用于替代传统SM30维护视图。该方案通过输入表名自动生成维护界面,支持动态筛选、批量操作和自动传输管理。核心设计包括:利用BAdI实现扩展点、通过行状态字段简化数据变更跟踪、使用Style Table控制单元格编辑权限、集成CTS实现自动传输。相比SM30标准维护,该框架显著提升了交互体验(支持ALV排序/过滤/汇总)和业务扩展性(统一校验与权限控制),同时解决了"维护+传输"流程割裂的问题。文中详细阐述了技术实现方案,并提

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 318

一款适用于 WPF 和 AvaloniaUI 的可定制颜色选择器控件

今天大姚给大家分享一款适用于 WPF 和 AvaloniaUI 的可定制颜色选择器控件:ColorPicker。ColorPicker 是一款适用于 WPF 和 AvaloniaUI 的可定制颜色选择器控件,支持 RGB、HSV、HSL 等多种色彩模式,能够轻松集成到你的 .NET 桌面应用中,为用户提供流畅精准的选色体验。

专注于C#/.NET/.NET Core学习、工作、面试干货和实战教程分享。这里聚焦了大量的C#/.NET/.NET Core优质文章、开源项目、实用工具和学习、工作、面试心得。 1093

R 语言 ggplot2 绘制精美高级全球地图

在本教程中,我们将学习如何使用R语言和ggplot2包绘制精美高级地图。ggplot2是一个功能强大的数据可视化包,它可以让我们创建漂亮、交互式的地图。我们将使用R中的一些其他包来处理地理空间数据,以便与ggplot2无缝协作。

Mrrunsen的博客 1866

哔哩下载姬跨平台版:全能B站视频下载解决方案终极指南

在当今数字内容爆炸的时代,哔哩下载姬跨平台版为B站视频爱好者提供了一套完整的下载解决方案。这款基于AvaloniaUI框架开发的开源工具,完美实现了Windows、Linux和macOS三大操作系统的全面覆盖,让用户能够轻松下载B站上的各类视频内容,包括8K超高清、HDR、杜比视界等高端格式,真正做到了跨平台视频下载的无缝体验。 ## 为什么选择哔哩下载姬跨平台版? ### 强大的技术架构支持

gitblog_00231的博客 403

美军利用MANET技术实现无人作战单元协同作战

本文首先介绍了移动自组织网络 (MANET)以及Wave Relay®波形中继技术,并探讨了波形中继MANET平台在美空军ABMS项目等军事方面的运用情况。

guanyifu9的博客 853

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

上一篇: net8使用ImageSharp检查jpg图片是否损坏
下一篇: vue3 带tabs的后台管理系统,切换tab标签后,共用界面带参数缓存界面状态
神色自若
博客等级 码龄19年 782粉丝 70原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神色自若

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值