WPF实现Modbus TCP通信客户端

一、概述:

使用:WPF、+ MVVM
Prism.DryIoc、system.IO.Ports、NMmodbus4

二、架构:

  • Views

    • MainWindow.xaml

  • Models

    • ModbusClient

  • ViewModels

    • MainWindowViewModel

  • Services

    • Interface

      • IModbusService

    • ModbusService

三、ModbusClient

public class ModbusClient { public ushort Address { get; set; } public ushort Value { get; set; } public string DisplayText => $"Addr {Address}: {Value}"; }

四、IModbusService

public interface IModbusService { Task<bool> ConnectAsync(string ipAddress, int port); Task<ushort[]> ReadHoldingRegistersAsync(ushort startAddress, ushort numberOfPoints); Task<bool> WriteSingleRegisterAsync(ushort address, ushort value); void Disconnect(); bool IsConnected { get; } }

五、ModbusService

public class ModbusService : IModbusService { private TcpClient? _tcpClient; private ModbusIpMaster? _master; public bool IsConnected => _tcpClient?.Connected == true && _master != null; public async Task<bool> ConnectAsync(string ipAddress, int port) { try { _tcpClient = new TcpClient(); await _tcpClient.ConnectAsync(ipAddress, port); if (!_tcpClient.Connected) return false; _master = ModbusIpMaster.CreateIp(_tcpClient); return true; } catch { Disconnect(); return false; } } public async Task<ushort[]> ReadHoldingRegistersAsync(ushort startAddress, ushort numberOfPoints) { if (!IsConnected || _master == null) throw new InvalidOperationException("Not connected to Modbus server."); return await Task.Run(() => _master.ReadHoldingRegisters(0, startAddress, numberOfPoints)); } public async Task<bool> WriteSingleRegisterAsync(ushort address, ushort value) { if (!IsConnected || _master == null) return false; await Task.Run(() => _master.WriteSingleRegister(0, address, value)); return true; } public void Disconnect() { _master?.Dispose(); _tcpClient?.Close(); _tcpClient?.Dispose(); _master = null; _tcpClient = null; } }

六、MainWindowViewModel

public class MainWindowViewModel : BindableBase { private readonly IModbusService _modbusService; private string _ipAddress = "127.0.0.1"; private int _port = 502; private ushort _startAddress = 0; private ushort _count = 10; private string _status = "Disconnected"; private ObservableCollection<ModbusClient> _modbusClient = new(); public string IpAddress { get => _ipAddress; set => SetProperty(ref _ipAddress, value); } public int Port { get => _port; set => SetProperty(ref _port, value); } public ushort StartAddress { get => _startAddress; set => SetProperty(ref _startAddress, value); } public ushort Count { get => _count; set => SetProperty(ref _count, value); } public string Status { get => _status; set => SetProperty(ref _status, value); } public ObservableCollection<ModbusClient> modbusClient { get => _modbusClient; set => SetProperty(ref _modbusClient, value); } public DelegateCommand ConnectCommand { get; } public DelegateCommand DisconnectCommand { get; } public DelegateCommand ReadRegistersCommand { get; } public MainWindowViewModel(IModbusService modbusService) { _modbusService = modbusService; ConnectCommand = new DelegateCommand(Connect); DisconnectCommand = new DelegateCommand(Disconnect); ReadRegistersCommand = new DelegateCommand(ReadRegisters); } private async void Connect() { var success = await _modbusService.ConnectAsync(IpAddress, Port); Status = success ? "Connected" : "Connection failed"; } private void Disconnect() { _modbusService.Disconnect(); Status = "Disconnected"; } private async void ReadRegisters() { try { var data = await _modbusService.ReadHoldingRegistersAsync(StartAddress, Count); modbusClient.Clear(); for (int i = 0; i < data.Length; i++) { modbusClient.Add(new ModbusClient { Address = (ushort)(StartAddress + i), Value = data[i], }); } } catch (Exception ex) { MessageBox.Show($"Error reading registers: {ex.Message}"); } } }

七、MainWindow.xaml

<Window x:Class="ModbusDemo.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ModbusDemo" mc:Ignorable="d" Title="Modbus TCP Client" Height="450" Width="800"> <Grid Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!-- Connection Panel --> <StackPanel Orientation="Horizontal" Margin="0,0,0,10"> <TextBox Text="{Binding IpAddress}" Width="120" Margin="0,0,5,0"/> <TextBox Text="{Binding Port}" Width="60" Margin="0,0,10,0"/> <Button Content="Connect" Command="{Binding ConnectCommand}" Width="80" Margin="0,0,5,0"/> <Button Content="Disconnect" Command="{Binding DisconnectCommand}" Width="80"/> </StackPanel> <!-- Status --> <TextBlock Grid.Row="1" Text="{Binding Status}" Margin="0,0,0,10"/> <!-- Read Panel --> <StackPanel Grid.Row="2" Orientation="Horizontal" VerticalAlignment="Top"> <TextBox Text="{Binding StartAddress}" Width="60" Margin="0,0,5,0"/> <TextBox Text="{Binding Count}" Width="50" Margin="0,0,10,0"/> <Button Content="Read Holding Registers" Command="{Binding ReadRegistersCommand}"/> </StackPanel> <!-- Register List --> <ListBox Grid.Row="2" Margin="0,40,0,0" ItemsSource="{Binding modbusClient}" > <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Address, StringFormat='Addr {0}: '}" FontWeight="Bold"/> <TextBlock Text="{Binding Value}"/> <TextBlock Text="{Binding DisplayText}" Margin="30 0"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Window>

八、MainWindow.xaml.cs

namespace ModbusDemo.Views { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } }

九、App.xaml

<prism:PrismApplication x:Class="ModbusDemo.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ModbusDemo" xmlns:prism="http://prismlibrary.com/"> <Application.Resources> </Application.Resources> </prism:PrismApplication>

十、App.xaml.cs

using ModbusDemo.Services.Interface; using ModbusDemo.Services; using ModbusDemo.Views; using System.Windows; using ModbusDemo.ViewModels; namespace ModbusDemo { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : PrismApplication { protected override Window CreateShell() { return Container.Resolve<MainWindow>(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterSingleton<IModbusService, ModbusService>(); containerRegistry.RegisterForNavigation<MainWindow, MainWindowViewModel>(); } } }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1150737.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenMV识别圆形物体:Hough变换算法通俗解释

OpenMV识别圆形物体&#xff1a;Hough变换算法通俗解释从一个常见问题说起你有没有遇到过这样的场景&#xff1f;想让机器人自动识别地上的乒乓球&#xff0c;或者检测仪表盘上的指针位置&#xff0c;又或是判断某个按钮是否被按下——这些任务的核心&#xff0c;都是在图像中找…

基于Java+SpringBoot+SSM商场停车场管理系统(源码+LW+调试文档+讲解等)/商场停车系统/停车场管理方案/商场停车解决方案/智能停车场管理系统/商场车辆管理系统/停车场智能化管理

博主介绍 &#x1f497;博主介绍&#xff1a;✌全栈领域优质创作者&#xff0c;专注于Java、小程序、Python技术领域和计算机毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f447;&#x1f3fb; 2025-2026年最新1000个热门Java毕业设计选题…

大规模设备接入下的USB2.0主机优化策略

如何让USB2.0在连接32个设备时依然稳如磐石&#xff1f;你有没有遇到过这样的场景&#xff1a;一个工业网关上插满了条码枪、传感器、摄像头&#xff0c;系统却频繁卡顿、设备掉线&#xff1f;明明用的是标准USB接口&#xff0c;怎么一到多设备就“罢工”&#xff1f;问题很可能…

扇出能力对比:TTL与CMOS驱动多个负载的表现分析

扇出能力对比&#xff1a;TTL与CMOS驱动多个负载的真实表现你有没有遇到过这种情况——在设计一个控制逻辑时&#xff0c;主控输出一个使能信号&#xff0c;要同时触发十几个外围芯片的输入引脚。结果系统偶尔失灵&#xff0c;测量发现高电平被“拉塌”了&#xff0c;明明应该是…

2026年课件制作新范式:AI PPT工具深度解析

随着2026年的临的到来&#xff0c;教育技术正以前所未有的速度演进。虚拟现实课堂、自适应学习平台与人工智能深度辅助已成为主流趋势。在这一背景下&#xff0c;作为课堂教学核心载体的课件PPT&#xff0c;其制作效率与质量直接关系到教学效果。 然而&#xff0c;面对日益增长…

基于Java+SpringBoot+SSM在线学习交流系统(源码+LW+调试文档+讲解等)/在线学习平台/学习交流系统/线上学习交流/网络学习交流/在线教育交流系统/学习互动系统

博主介绍 &#x1f497;博主介绍&#xff1a;✌全栈领域优质创作者&#xff0c;专注于Java、小程序、Python技术领域和计算机毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f447;&#x1f3fb; 2025-2026年最新1000个热门Java毕业设计选题…

PCB封装基础:通俗解释引脚间距与焊盘设计

PCB封装设计实战指南&#xff1a;从引脚间距到焊盘布局的工程细节你有没有遇到过这样的情况&#xff1f;——原理图画得一丝不苟&#xff0c;PCB布线也干干净净&#xff0c;结果一到SMT贴片环节&#xff0c;QFN芯片回流后“翘起一只脚”&#xff0c;或者细间距QFP满屏桥连&…

AD导出Gerber文件在CAM软件中的后续处理方法

从AD到工厂&#xff1a;Gerber文件在CAM中的实战处理全解析你有没有遇到过这样的情况&#xff1f;辛辛苦苦在Altium Designer里画完板子&#xff0c;信心满满地导出Gerber发给厂家&#xff0c;结果三天后收到一封邮件&#xff1a;“贵司资料存在层偏、阻焊开窗异常&#xff0c;…

基于Java+SpringBoot+SSM在线网络学习平台(源码+LW+调试文档+讲解等)/在线学习平台/网络学习平台/在线教育平台/网络教育平台/线上学习平台/线上教育平台/网络课程平台

博主介绍 &#x1f497;博主介绍&#xff1a;✌全栈领域优质创作者&#xff0c;专注于Java、小程序、Python技术领域和计算机毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f447;&#x1f3fb; 2025-2026年最新1000个热门Java毕业设计选题…

理想二极管在电源管理中的应用原理深度剖析

理想二极管&#xff1a;如何用MOSFET“伪装”成零压降二极管&#xff0c;彻底告别发热与效率瓶颈&#xff1f;你有没有遇到过这样的场景&#xff1a;一个看似简单的电源切换电路&#xff0c;却因为用了几个肖特基二极管&#xff0c;导致板子烫得不敢摸&#xff1f;或者在做电池…

[特殊字符]_Web框架性能终极对决:谁才是真正的速度王者[20260112164948]

作为一名拥有10年开发经验的全栈工程师&#xff0c;我经历过无数Web框架的兴衰更替。从早期的jQuery时代到现在的Rust高性能框架&#xff0c;我见证了Web开发技术的飞速发展。今天我要分享一个让我震惊的性能对比测试&#xff0c;这个测试结果彻底改变了我对Web框架性能的认知。…

基于Java+SpringBoot+SSM在线食品安全信息平台(源码+LW+调试文档+讲解等)/在线食品监管信息平台/食品安全在线查询平台/网络食品安全信息平台/在线食品信息公示平台

博主介绍 &#x1f497;博主介绍&#xff1a;✌全栈领域优质创作者&#xff0c;专注于Java、小程序、Python技术领域和计算机毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f447;&#x1f3fb; 2025-2026年最新1000个热门Java毕业设计选题…

趋势科技:速修复这个严重的 Apex Central RCE漏洞

聚焦源代码安全&#xff0c;网罗国内外最新资讯&#xff01;编译&#xff1a;代码卫士趋势科技修复了位于 Apex Central 本地版中的一个严重漏洞CVE-2025-69258&#xff0c;可导致攻击者以系统权限执行任意代码。Apex Central 是一款基于 web 的管理面板&#xff0c;帮助管理员…

Java Web 中小型医院网站系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

摘要 随着信息技术的快速发展&#xff0c;医疗行业的信息化建设已成为提升医院管理效率和服务质量的重要途径。传统医院管理系统存在功能单一、扩展性差、用户体验不佳等问题&#xff0c;难以满足现代医院管理的需求。中小型医院亟需一套高效、稳定且易于维护的网站系统&#x…

电商运营中的数据驱动的决策流程

电商运营中的数据驱动的决策流程关键词&#xff1a;电商运营、数据驱动、决策流程、数据分析、商业智能摘要&#xff1a;本文围绕电商运营中数据驱动的决策流程展开深入探讨。首先介绍了该主题的背景&#xff0c;包括目的、预期读者、文档结构和相关术语。接着阐述了核心概念及…

基于Java+SpringBoot+SSM在线骑行网站(源码+LW+调试文档+讲解等)/在线骑行平台/骑行在线网站/骑行网站推荐/在线骑行服务网站/骑行爱好者网站/骑行活动在线网站

博主介绍 &#x1f497;博主介绍&#xff1a;✌全栈领域优质创作者&#xff0c;专注于Java、小程序、Python技术领域和计算机毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f447;&#x1f3fb; 2025-2026年最新1000个热门Java毕业设计选题…

Elasticsearch搜索优化:超详细版查询性能调优指南

Elasticsearch搜索性能调优实战&#xff1a;从面试题到生产级优化你有没有遇到过这样的场景&#xff1f;凌晨三点&#xff0c;监控系统突然报警&#xff1a;Elasticsearch集群CPU飙升至95%&#xff0c;Kibana查询超时&#xff0c;日志检索几乎瘫痪。而罪魁祸首&#xff0c;可能…

USB接口有几种?图文详解主流类型

USB接口有几种&#xff1f;从“插不准”到“一线通”的演进之路 你有没有过这样的经历&#xff1a;手机没电了&#xff0c;急着充电&#xff0c;可那根USB线就是“死活插不进去”&#xff1f;翻来覆去试了三次&#xff0c;才对准方向——别怀疑自己&#xff0c;这正是 传统USB…

​[特殊字符]1 概述文献来源:基于多能互补的热电联供型微网优化运行研究CHP-MG 系统供给侧多能互补模型本文主要研究包含热、电、气 3 种能源形式的CHP-MG 系统优化运行

&#x1f468;‍&#x1f393;个人主页 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&a…

收到工资 1002415.13 元,爱你华为!!!

昨夜&#xff0c;一位华为员工从传统开发岗成功转岗到算法大模型岗&#xff0c;在网上晒出自己100w的工资条并大胆示“爱”&#xff0c;在行业内掀起了阵阵热潮。如今&#xff0c;这股强劲的AI之风&#xff0c;终究还是吹到了后端领域&#xff0c;既是风险&#xff0c;也是机遇…