This commit is contained in:
xyy
2026-05-15 20:39:11 +08:00
parent 873dbe61bb
commit 10f5cbfd53
15 changed files with 534 additions and 101 deletions

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<TargetFramework>net10.0-windows7.0</TargetFramework>
<RootNamespace>ASTM_D7896_19瞬态热线法</RootNamespace>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
@@ -11,6 +11,12 @@
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
<PackageReference Include="EPPlus" Version="7.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="10.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="10.0.8" />
<PackageReference Include="NModbus4.NetCore" Version="4.0.0" />
<PackageReference Include="OxyPlot.Wpf" Version="2.2.0" />
</ItemGroup>
@@ -20,4 +26,8 @@
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Models\" />
</ItemGroup>
</Project>

View File

@@ -1,8 +1,8 @@
<Application x:Class="ASTM_D7896_Tester.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:ASTM_D7896_Tester.Converters"
StartupUri="Views/MainWindow.xaml">
xmlns:converters="clr-namespace:ASTM_D7896_Tester.Converters"
>
<Application.Resources>
<converters:InverseBooleanConverter x:Key="InverseBooleanConverter"/>

View File

@@ -1,14 +1,71 @@
using System.Configuration;
using ASTM_D7896_Tester.Models;
using ASTM_D7896_Tester.Services;
using ASTM_D7896_Tester.Views;
using Microsoft.Extensions.Configuration;
using OfficeOpenXml;
using System;
using System.Configuration;
using System.Data;
using System.IO;
using System.Windows;
namespace ASTM_D7896_Tester.Views
namespace ASTM_D7896_Tester
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public static IPlcService PlcService { get; private set; }
public static AppConfig PlcConfig { get; private set; }
protected override async void OnStartup(StartupEventArgs e)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
base.OnStartup(e);
// 防止在登录窗口关闭时应用程序因没有窗口而自动退出
ShutdownMode = ShutdownMode.OnExplicitShutdown;
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
var configuration = builder.Build();
// appsettings.json in this project keeps PLC settings at the root of the file
// (not under a "PlcSettings" section). Bind the entire configuration to AppConfig.
PlcConfig = configuration.Get<AppConfig>() ?? new AppConfig();
PlcService = new PlcService(PlcConfig);
var plcService = App.PlcService as PlcService;
try
{
await plcService.EnsureConnectedAsync();
}
catch (Exception ex)
{
MessageBox.Show($"PLC 连接失败:{ex.Message}");
}
// 启动主窗口,设置为应用程序的主窗口并恢复默认的退出模式
var mainWindow = new MainWindow();
MainWindow = mainWindow;
ShutdownMode = ShutdownMode.OnMainWindowClose;
mainWindow.Show();
}
protected override void OnExit(ExitEventArgs e)
{
(PlcService as IDisposable)?.Dispose();
base.OnExit(e);
}
}
}

View File

@@ -8,6 +8,7 @@ public class AppConfig
public PlcRegisterAddresses PlcRegisterAddresses { get; set; } = new();
public TestParameters TestParameters { get; set; } = new();
public AppSettings AppSettings { get; set; } = new();
}
public class PlcConnectionConfig
@@ -15,15 +16,18 @@ public class PlcConnectionConfig
public string IpAddress { get; set; } = "127.0.0.1";
public int Port { get; set; } = 502;
public int TimeoutMs { get; set; } = 5000;
public byte SlaveId { get; set; } = 1; // 从站地址默认1
}
public class PlcRegisterAddresses
{
public int ThermalConductivity { get; set; } = 40001;
public int ThermalDiffusivity { get; set; } = 40003;
public int TestTemperature { get; set; } = 40005;
public int StartCommand { get; set; } = 40010;
public int ResetCommand { get; set; } = 40011;
public ushort ThermalConductivity { get; set; } = 40001;
public ushort ThermalDiffusivity { get; set; } = 40003;
public ushort TestTemperature { get; set; } = 40005;
public ushort StartCommand { get; set; } = 40010;
public ushort ResetCommand { get; set; } = 40011;
}
public class TestParameters
@@ -43,6 +47,8 @@ public class TestParameters
public bool UsePressure { get; set; } = false;
public string ReferenceLiquid { get; set; } = "蒸馏水";
public double ReferenceConductivity { get; set; } = 0.606;
public CalibrationCoefficients CalibrationCoefficients { get; set; } = new();
}
public class AppSettings
@@ -50,4 +56,12 @@ public class AppSettings
public int WindowWidth { get; set; } = 1024;
public int WindowHeight { get; set; } = 768;
public string ThemeColor { get; set; } = "Blue";
}
public class CalibrationCoefficients
{
public ushort PressureCoefficient { get; set; }
public ushort PressureProtection { get; set; }
public ushort TemperatureCoefficient { get; set; }
public ushort ResistanceCoefficient { get; set; }
}

View File

@@ -1,11 +0,0 @@
namespace ASTM_D7896_Tester.Services;
public interface IPlcCommunicationService
{
Task<bool> ConnectAsync();
Task DisconnectAsync();
Task<bool> IsConnectedAsync();
Task<float> ReadFloatAsync(int address);
Task WriteSingleCoilAsync(int address, bool value);
Task WriteSingleRegisterAsync(int address, short value);
}

39
Services/IPlcService.cs Normal file
View File

@@ -0,0 +1,39 @@
namespace ASTM_D7896_Tester.Services;
public interface IPlcService
{
Task<bool> ConnectAsync();
Task DisconnectAsync();
Task<bool> IsConnectedAsync();
/// <summary> 读取指定工位的压力(浮点数) </summary>
/// <param name="stationId">工位号 1~3</param>
//Task<float> ReadPressureAsync(int stationId);
/// <summary> 读取湿膜流量(浮点数) </summary>
Task<float> ReadWetFlowAsync(int stationId);
/// <summary> 读取干膜流量(浮点数) </summary>
Task<float> ReadDryFlowAsync(int stationId);
/// <summary> 写入线圈(如 M 元件) </summary>
Task WriteCoilAsync(ushort coilAddress, bool value);
/// <summary> 写入单个寄存器16位 </summary>
Task WriteRegisterAsync(ushort registerAddress, ushort value);
/// <summary> 读取线圈状态(如 M 元件的 ON/OFF </summary>
Task<bool> ReadCoilAsync(ushort coilAddress);
/// <summary> 读取连续多个保持寄存器16位 </summary>
Task<ushort[]> ReadHoldingRegistersAsync(ushort startAddress, ushort count);
/// <summary> 写入单个保持寄存器16位 </summary>
Task WriteSingleRegisterAsync(ushort registerAddress, ushort value);
Task WriteMultipleRegistersAsync(ushort registerAddress, float value);
float UshortToFloat(ushort P1, ushort P2);
Task<float> ReadFloatAsync(ushort startAddress);
}

View File

@@ -1,51 +0,0 @@
using System;
using System.Threading.Tasks;
namespace ASTM_D7896_Tester.Services;
public class PlcCommunicationService : IPlcCommunicationService
{
private bool _isConnected = false;
private readonly Random _random = new();
public Task<bool> ConnectAsync()
{
// 模拟连接
_isConnected = true;
return Task.FromResult(true);
}
public Task DisconnectAsync()
{
_isConnected = false;
return Task.CompletedTask;
}
public Task<bool> IsConnectedAsync() => Task.FromResult(_isConnected);
public Task<float> ReadFloatAsync(int address)
{
// 模拟读取PLC寄存器返回随机值实际应通过协议读取
// 热导率范围 0.1~1.0 W/m·K热扩散率范围 0.05~1.5 ×10⁻⁶ m²/s
if (address == 40001)
return Task.FromResult((float)(0.2 + _random.NextDouble() * 0.8));
if (address == 40003)
return Task.FromResult((float)(0.1 + _random.NextDouble() * 1.0));
if (address == 40005)
return Task.FromResult(25.0f); // 测试温度
return Task.FromResult(0.0f);
}
public Task WriteSingleCoilAsync(int address, bool value)
{
// 模拟写入线圈
System.Diagnostics.Debug.WriteLine($"Write coil {address} = {value}");
return Task.CompletedTask;
}
public Task WriteSingleRegisterAsync(int address, short value)
{
System.Diagnostics.Debug.WriteLine($"Write register {address} = {value}");
return Task.CompletedTask;
}
}

212
Services/PlcService.cs Normal file
View File

@@ -0,0 +1,212 @@
using ASTM_D7896_Tester.Models;
using Modbus.Device;
using System;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace ASTM_D7896_Tester.Services;
public class PlcService : IPlcService
{
private bool _isConnected = false;
private readonly AppConfig _config;
private TcpClient _tcpClient;
private IModbusMaster _master;
public PlcService(AppConfig config)
{
_config = config;
}
public Task<bool> ConnectAsync()
{
// 模拟连接
_isConnected = true;
return Task.FromResult(true);
}
public Task DisconnectAsync()
{
_isConnected = false;
return Task.CompletedTask;
}
public Task<bool> IsConnectedAsync() => Task.FromResult(_isConnected);
public async Task EnsureConnectedAsync(int retryCount = 3)
{
if (_tcpClient != null && _tcpClient.Connected)
return;
for (int i = 0; i < retryCount; i++)
{
try
{
_tcpClient?.Close();
_tcpClient = new TcpClient();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3));
// 现在可以直接使用扩展方法
await _tcpClient.ConnectAsync(_config.PlcConnection.IpAddress, _config.PlcConnection.Port).WithCancellation(cts.Token);
_master = ModbusIpMaster.CreateIp(_tcpClient);
return;
}
catch (Exception ex) when (i < retryCount - 1)
{
System.Diagnostics.Debug.WriteLine($"连接失败,{500}ms 后重试... {ex.Message}");
await Task.Delay(500);
}
}
throw new Exception($"无法连接到 PLC ({_config.PlcConnection.IpAddress}:{_config.PlcConnection.Port}),请检查网络和 PLC 状态。");
}
// 读取两个连续的保持寄存器转换为32位浮点数假设大端模式
public async Task<float> ReadFloatAsync(ushort startAddress)
{
await EnsureConnectedAsync();
var registers = await ReadHoldingRegistersAsync(startAddress, 2);
return UshortToFloat(registers[1], registers[0]);
}
//public async Task<float> ReadPressureAsync() =>
// await ReadFloatAsync(_config.PressureRegister);
public async Task<float> ReadWetFlowAsync(int stationId)
{
ushort startAddress = stationId switch
{
//1 => _config.WetFlowRegister,
//2 => _config.WetFlowRegister2,
//3 => _config.WetFlowRegister3,
};
return await ReadFloatAsync(startAddress);
}
public async Task<float> ReadDryFlowAsync(int stationId)
{
ushort startAddress = stationId switch
{
_ => throw new ArgumentException("Invalid station")
};
return await ReadFloatAsync(startAddress);
}
public async Task WriteCoilAsync(ushort coilAddress, bool value)
{
await EnsureConnectedAsync();
await _master.WriteSingleCoilAsync(_config.PlcConnection.SlaveId, coilAddress, value);
}
public async Task WriteRegisterAsync(ushort registerAddress, ushort value)
{
await EnsureConnectedAsync();
await Task.Delay(100);
await _master.WriteSingleRegisterAsync(_config.PlcConnection.SlaveId, registerAddress, value);
}
public async Task<bool> ReadCoilAsync(ushort coilAddress)
{
await EnsureConnectedAsync();
await Task.Delay(100);
bool[] result = await _master?.ReadCoilsAsync(_config.PlcConnection.SlaveId, coilAddress, 1);
return result[0];
}
public bool IsConnected => _tcpClient != null && _tcpClient.Connected;
public async Task<ushort[]> ReadHoldingRegistersAsync(ushort startAddress, ushort count)
{
await EnsureConnectedAsync();
// await Task.Delay(100);
return await _master.ReadHoldingRegistersAsync(_config.PlcConnection.SlaveId, startAddress, count);
}
public async Task WriteSingleRegisterAsync(ushort registerAddress, ushort value)
{
await EnsureConnectedAsync();
int val = (int)value;
await Task.Delay(100);
await _master.WriteMultipleRegistersAsync(1, registerAddress, intToushorts(val));
}
public async Task WriteMultipleRegistersAsync(ushort registerAddress, float value)
{
await EnsureConnectedAsync();
await Task.Delay(100);
await _master.WriteMultipleRegistersAsync(_config.PlcConnection.SlaveId, registerAddress, SplitFloatToUShortArray((float)value));
}
/// <summary>
/// Int转为ushort数组发送
/// </summary>
/// <param name="res"></param>
/// <returns>返回ushort数组</returns>
private ushort[] intToushorts(int res)
{
ushort ust1 = (ushort)(res >> 16);
ushort ust2 = (ushort)res;
return new ushort[] { ust2, ust1 };
}
/// <summary>
/// Float转为Ushort数组发送
/// </summary>
/// <param name="value"></param>
/// <returns>返回ushort数组</returns>
public ushort[] SplitFloatToUShortArray(float value)
{
byte[] floatBytes = BitConverter.GetBytes(value);
ushort[] ushortArray = new ushort[floatBytes.Length / 2];
for (int i = 0, j = 0; i < floatBytes.Length; i += 2, j++)
{
ushortArray[j] = BitConverter.ToUInt16(floatBytes, i);
}
return ushortArray;
}
/// <summary>
/// ushort转为float类型
/// </summary>
/// <param name="P1"></param>
/// <param name="P2"></param>
/// <returns>float型数据</returns>
public float UshortToFloat(ushort P1, ushort P2)
{
int intSign, intSignRest, intExponent, intExponentRest;
float faResult, faDigit;
intSign = P1 / 32768;
intSignRest = P1 % 32768;
intExponent = intSignRest / 128;
intExponentRest = intSignRest % 128;
faDigit = (float)(intExponentRest * 65536 + P2) / 8388608;
faResult = (float)Math.Pow(-1, intSign) * (float)Math.Pow(2, intExponent - 127) * (faDigit + 1);
return faResult;
}
public void Dispose()
{
_master?.Dispose();
_tcpClient?.Close();
_tcpClient?.Dispose();
}
}
public static class TaskExtensions
{
public static async Task WithCancellation(this Task task, CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<bool>();
using (cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs))
{
if (task != await Task.WhenAny(task, tcs.Task))
throw new OperationCanceledException(cancellationToken);
}
await task;
}
}

View File

@@ -0,0 +1,85 @@
using ASTM_D7896_Tester.Models;
using ASTM_D7896_Tester.Services;
using ASTM_D7896_Tester.Views;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Threading.Tasks;
using System.Windows;
using static ASTM_D7896_Tester.Models.TestParameters;
namespace ASTM_D7896_Tester.ViewModels;
public partial class ConfigViewModel : ObservableObject
{
[ObservableProperty]
private float _pressureCoefficient;
[ObservableProperty]
private float _pressureProtection;
[ObservableProperty]
private float _temperatureCoefficient;
[ObservableProperty]
private float _resistanceCoefficient;
private readonly IPlcService _plcService;
private readonly AppConfig _coefficientAddresses;
public ConfigViewModel()
{
// 从 App 静态属性获取 PLC 服务和系数寄存器地址
_plcService = ASTM_D7896_Tester.App.PlcService;
_coefficientAddresses = ASTM_D7896_Tester.App.PlcConfig;
// 窗口打开时加载一次
LoadFromPlc();
}
private async void LoadFromPlc()
{
try
{
PressureCoefficient = await _plcService.ReadFloatAsync(_coefficientAddresses.TestParameters.CalibrationCoefficients.PressureCoefficient);
PressureProtection = await _plcService.ReadFloatAsync(_coefficientAddresses.TestParameters.CalibrationCoefficients.PressureProtection);
TemperatureCoefficient = await _plcService.ReadFloatAsync(_coefficientAddresses.TestParameters.CalibrationCoefficients.TemperatureCoefficient);
ResistanceCoefficient = await _plcService.ReadFloatAsync(_coefficientAddresses.TestParameters.CalibrationCoefficients.ResistanceCoefficient);
}
catch (Exception ex)
{
MessageBox.Show($"从 PLC 读取系数失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
[RelayCommand]
private async Task Save()
{
try
{
// 写入 PLC使用 WriteMultipleRegistersAsync该方法支持 float
await _plcService.WriteMultipleRegistersAsync(_coefficientAddresses.TestParameters.CalibrationCoefficients.PressureCoefficient, PressureCoefficient);
await _plcService.WriteMultipleRegistersAsync(_coefficientAddresses.TestParameters.CalibrationCoefficients.PressureProtection, PressureProtection);
await _plcService.WriteMultipleRegistersAsync(_coefficientAddresses.TestParameters.CalibrationCoefficients.TemperatureCoefficient, TemperatureCoefficient);
await _plcService.WriteMultipleRegistersAsync(_coefficientAddresses.TestParameters.CalibrationCoefficients.ResistanceCoefficient, ResistanceCoefficient);
MessageBox.Show("系数已保存到 PLC。", "成功", MessageBoxButton.OK, MessageBoxImage.Information);
CloseWindow();
}
catch (Exception ex)
{
MessageBox.Show($"保存失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
[RelayCommand]
private void Cancel()
{
CloseWindow();
}
private void CloseWindow()
{
Application.Current.Windows.OfType<ConfigWindow>().FirstOrDefault()?.Close();
}
}

View File

@@ -17,9 +17,10 @@ namespace ASTM_D7896_Tester.ViewModels;
public partial class D7896ViewModel : ObservableObject
{
private readonly IPlcCommunicationService _plcService;
private readonly ReportService _reportService;
private readonly IPlcService _plcService;
private AppConfig _config;
private readonly ReportService _reportService;
public ObservableCollection<string> ReferenceLiquids { get; } = new ObservableCollection<string> { "蒸馏水", "甲苯", "乙二醇" };
@@ -119,8 +120,10 @@ public partial class D7896ViewModel : ObservableObject
public D7896ViewModel()
{
_config = JsonConfigHelper.LoadConfig();
_plcService = new PlcCommunicationService();
// 获取应用全局配置并确保不为 null
_config = ASTM_D7896_Tester.App.PlcConfig ?? new Models.AppConfig();
_plcService = ASTM_D7896_Tester.App.PlcService;
_reportService = new ReportService(_config.TestParameters.ReportOutputPath);
// 加载配置中的默认值
@@ -198,9 +201,9 @@ public partial class D7896ViewModel : ObservableObject
CurrentMeasurementIndex = i;
StatusMessage = $"正在执行第 {i} 次测量...";
await _plcService.WriteSingleCoilAsync(_config.PlcRegisterAddresses.StartCommand, true);
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, true);
await Task.Delay(500);
await _plcService.WriteSingleCoilAsync(_config.PlcRegisterAddresses.StartCommand, false);
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, false);
await Task.Delay(2000);
@@ -461,9 +464,9 @@ public partial class D7896ViewModel : ObservableObject
if (!await _plcService.IsConnectedAsync())
await _plcService.ConnectAsync();
await _plcService.WriteSingleCoilAsync(_config.PlcRegisterAddresses.StartCommand, true);
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, true);
await Task.Delay(500);
await _plcService.WriteSingleCoilAsync(_config.PlcRegisterAddresses.StartCommand, false);
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, false);
await Task.Delay(2000);
float lambda = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.ThermalConductivity);

44
Views/ConfigWindow.xaml Normal file
View File

@@ -0,0 +1,44 @@
<Window x:Class="ASTM_D7896_Tester.Views.ConfigWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="高级参数配置" Height="300" Width="400"
WindowStartupLocation="CenterOwner">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="校准系数配置" FontWeight="Bold" FontSize="16" Grid.Row="0" Margin="0,0,0,15"/>
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,5">
<TextBlock Text="压力系数 (D1328):" Width="150" VerticalAlignment="Center"/>
<TextBox Text="{Binding PressureCoefficient ,UpdateSourceTrigger=LostFocus}" Width="100"/>
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Horizontal" Margin="0,5">
<TextBlock Text="压力保护 (kPa) (D1332):" Width="150" VerticalAlignment="Center"/>
<TextBox Text="{Binding PressureProtection,UpdateSourceTrigger=LostFocus}" Width="100"/>
<TextBlock Text="(超此值停止测试)" Margin="10,0,0,0" Foreground="Gray" FontSize="11"/>
</StackPanel>
<StackPanel Grid.Row="3" Orientation="Horizontal" Margin="0,5">
<TextBlock Text="温度系数 (D1378):" Width="150" VerticalAlignment="Center"/>
<TextBox Text="{Binding TemperatureCoefficient ,UpdateSourceTrigger=LostFocus}" Width="100"/>
</StackPanel>
<StackPanel Grid.Row="4" Orientation="Horizontal" Margin="0,5">
<TextBlock Text="电阻系数 (D1428):" Width="150" VerticalAlignment="Center"/>
<TextBox Text="{Binding ResistanceCoefficient,UpdateSourceTrigger=LostFocus}" Width="100"/>
</StackPanel>
<StackPanel Grid.Row="5" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,20,0,0">
<Button Content="保存并关闭" Command="{Binding SaveAndCloseCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}" Width="100" Margin="5"/>
<Button Content="取消" Click="CancelButton_Click" Width="100" Margin="5"/>
</StackPanel>
</Grid>
</Window>

View File

@@ -0,0 +1,18 @@
using System.Windows;
using ASTM_D7896_Tester.ViewModels;
namespace ASTM_D7896_Tester.Views;
public partial class ConfigWindow : Window
{
public ConfigWindow()
{
InitializeComponent();
DataContext = new ConfigViewModel();
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
Close();
}
}

View File

@@ -1,4 +1,6 @@
using ASTM_D7896_Tester.ViewModels;
using ASTM_D7896_Tester.Models;
using ASTM_D7896_Tester.Services;
using ASTM_D7896_Tester.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -21,10 +23,11 @@ namespace ASTM_D7896_Tester.Views
/// </summary>
public partial class D7896View : UserControl
{
public D7896View()
{
InitializeComponent();
DataContext = new D7896ViewModel(); // 或者从外部注入
DataContext = new D7896ViewModel();
}
}
}

View File

@@ -1,24 +1,28 @@
using System.Text;
using ASTM_D7896_Tester.Views;
using CommunityToolkit.Mvvm.Input;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ASTM_D7896_Tester.Views
namespace ASTM_D7896_Tester.Views;
public partial class MainWindow : Window
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
public MainWindow()
{
public MainWindow()
{
InitializeComponent();
}
InitializeComponent();
// 注册快捷键
KeyGesture keyGesture = new KeyGesture(Key.P, ModifierKeys.Control);
var inputBinding = new InputBinding(OpenConfigCommand, keyGesture);
this.InputBindings.Add(inputBinding);
}
private ICommand _openConfigCommand;
public ICommand OpenConfigCommand => _openConfigCommand ??= new RelayCommand(OpenConfig);
private void OpenConfig()
{
var configWindow = new ConfigWindow();
configWindow.Owner = this;
configWindow.ShowDialog();
}
}

View File

@@ -1,6 +1,6 @@
{
"PlcConnection": {
"IpAddress": "192.168.1.100",
"IpAddress": "127.0.0.1",
"Port": 502,
"TimeoutMs": 5000
},
@@ -21,7 +21,13 @@
"DefaultPressure": 0.0,
"UsePressure": false,
"ReferenceLiquid": "蒸馏水",
"ReferenceConductivity": 0.606
"ReferenceConductivity": 0.606,
"CalibrationCoefficients": {
"PressureCoefficient": 1328,
"PressureProtection": 1332,
"TemperatureCoefficient": 1378,
"ResistanceCoefficient": 1428
}
},
"AppSettings": {
"WindowWidth": 1024,