Files
Sleep-Multi-functionality/Window6.xaml.cs
2026-05-04 14:46:58 +08:00

1040 lines
35 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Modbus.Device;
using Modbus;
using OxyPlot.Series;
using OxyPlot;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
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.Shapes;
using System.Windows.Threading;
using OxyPlot.Axes;
using OxyPlot.Legends;
using ;
namespace ShanghaiEnvironmentalTechnology
{
/// <summary>
/// Window6.xaml 的交互逻辑
/// </summary>
public partial class Window6 : Window
{
DataChange c = new DataChange();
#region /线
// 控制线圈M代码
private readonly ushort _OutBreathUpAddress = 0x0011; // 呼上M17
private readonly ushort _OutBreathDownAddress = 0x0010; // 呼下M16
private readonly ushort _InBreathUpAddress = 0x001E; // 吸上M30
private readonly ushort _InBreathDownAddress = 0x001F; // 吸下M31
private readonly ushort _HandInBreathUpAddress = 0x0013; // 手动吸M19
private readonly ushort _HandInBreathDownAddress = 0x0012; // 手动呼M18
private readonly ushort _BreathUpAddress = 0x002A; // 呼气校准M42
private readonly ushort _BreathDownAddress = 0x002B; // 吸气校准M43
private readonly ushort _PressCheckAddress = 41; // 压力校准M41
Function fc;
#endregion
#region /线
// 控制线圈D代码
private readonly ushort _handSpeedAddress = 218; // 手动速度D218
//潮气量系数
private readonly ushort _moistureAddress = 3700;
//设置呼气流量系数 D1218呼流量系数
private readonly ushort _OutFowRateAddress = 1218; // 手动速度D1218呼流量系数
//设置吸气流量系数 D1318呼流量系数
private readonly ushort _InFowRateAddress = 1318; // 手动速度D1318呼流量系数
//设置压力系数 D1118
private readonly ushort _PressRateAddress = 1118; // 手动速度D1118
//位置
private readonly ushort _PositionAddress = 0x002A; // D42
//压力
private readonly ushort _PressAddress = 0x0BD6; // 手动速度D3030
//呼气流量
private readonly ushort _OutBreathAddress = 0x1398; // D5016
//吸气流量
private readonly ushort _InBreathAddress = 0x1396; // D5014
//复位
private readonly ushort _resetAddress = 0x0002; // D5014
#endregion
// 定时器(按功能分组)
private System.Timers.Timer _ReadTimer; // 实时监控数据
// Modbus通信
private TcpClient _tcpClient;
private IModbusMaster _modbusMaster;
private System.Timers.Timer resetTimer; // 启动状态实时定时器
#region
private PlotModel _plotModel;
private LineSeries _exhalationSeries;
private LineSeries _inhalationSeries;
private List<DataPoint> _exhalationData;
private List<DataPoint> _inhalationData;
private int _timeCounter;
#region ++
// 编辑状态标志位(控制定时器是否更新)
private bool _isEditingHandmovement; // 手动速度
private bool _isEditingMoisture; // 潮气量系数
private bool _isEditingOutFlow; // 呼气流量系数
private bool _isEditingInFlow; // 吸气流量系数
private bool _isEditingPress; // 压力系数
// 实时读取定时器1个定时器管理5个参数
private System.Timers.Timer _paramReadTimer;
// 下位机寄存器地址根据实际PLC地址修改
//private readonly ushort _handmovementAddr = 0x0300; // 手动速度
//private readonly ushort _moistureAddr = 0x0301; // 潮气量系数
//private readonly ushort _outFlowAddr = 0x0302; // 呼气流量系数
//private readonly ushort _inFlowAddr = 0x0303; // 吸气流量系数
//private readonly ushort _pressAddr = 0x0304; // 压力系数
#endregion
private void OnResetTimerElapsed(object sender, ElapsedEventArgs e)
{
try
{
bool[] result = _modbusMaster?.ReadCoils(0x01, 3, 1);
bool isTestRunning = result != null && result.Length > 0 && result[0];
ResetBtn.Dispatcher.Invoke(() =>
{
if (isTestRunning)
{
ResetBtn.Content = "复位成功";
ResetBtn.Foreground = Brushes.LightGreen;
}
else
{
ResetBtn.Content = "复位";
ResetBtn.Foreground = Brushes.White;
}
});
}
catch (Exception ex)
{
Console.WriteLine($"读取线圈或更新UI失败{ex.Message}");
}
}
#endregion
public Window6()
{
InitializeComponent();
InitializeModbusTcp();
InitializePlot();
StartDataUpdate();
_paramReadTimer = new System.Timers.Timer(1000) { AutoReset = true, Enabled = true };
_paramReadTimer.Elapsed += OnParamTimerElapsed; // 绑定定时读取事件
resetTimer = CreateTimer(1000, OnResetTimerElapsed);
Loaded += (s, e) => _paramReadTimer.Start();
//Hertbean();
}
#region UI
private void OnParamTimerElapsed(object sender, ElapsedEventArgs e)
{
// 1. 手动速度(焦点不在时更新)
if (!_isEditingHandmovement)
{
ReadAndUpdateParam(
address: _handSpeedAddress,
isFloat: true,
updateAction: (value) => UpdateTextBox(handmovementTxt, value.ToString())
);
}
// 2. 潮气量系数
if (!_isEditingMoisture)
{
ReadAndUpdateParam(
address: _moistureAddress,
isFloat: true,
updateAction: (value) => UpdateTextBox(moistureTxt, value.ToString())
);
}
// 3. 呼气流量系数
if (!_isEditingOutFlow)
{
ReadAndUpdateParam(
address: _OutFowRateAddress,
isFloat: true,
updateAction: (value) => UpdateTextBox(OutFowRateTxt, value.ToString())
);
}
// 4. 吸气流量系数
if (!_isEditingInFlow)
{
ReadAndUpdateParam(
address: _InFowRateAddress,
isFloat: true,
updateAction: (value) => UpdateTextBox(InFowRateTxt, value.ToString())
);
}
// 5. 压力系数
if (!_isEditingPress)
{
ReadAndUpdateParam(
address: _PressRateAddress,
isFloat: true,
updateAction: (value) => UpdateTextBox(PressRateTxt, value.ToString())
);
}
}
#endregion
// 读取下位机参数通用方法
private void ReadAndUpdateParam(ushort address, bool isFloat, Action<object> updateAction)
{
if (!IsModbusConnected())
{
updateAction("离线");
return;
}
try
{
ushort[] data = _modbusMaster?.ReadHoldingRegisters(0x01, address, isFloat ? (ushort)2 : (ushort)1);
object value = isFloat
? Convert.ToSingle(c.UshortToFloat(data[1], data[0])) // 浮点数(需转换)
: data[0]; // 整数
updateAction(value);
}
catch
{
updateAction("读取失败");
}
}
private void UpdateTextBox(TextBox textBox, string value)
{
Dispatcher.Invoke(() =>
{
if (textBox.IsVisible) // 控件可见时才更新
{
textBox.Text = value;
}
});
}
private void InitializePlot()
{
_plotModel = new PlotModel
{
Title = "呼气流量与吸气流量",
Background = OxyColor.FromRgb(240, 240, 240) // 设置背景色
};
_exhalationSeries = new LineSeries
{
Title = "呼气流量 (D5016)",
Color = OxyColor.FromRgb(255, 0, 0),
StrokeThickness = 2, // 设置线条宽度
MarkerType = MarkerType.Circle, // 添加标记
MarkerSize = 4
};
_inhalationSeries = new LineSeries
{
Title = "吸气流量 (D5014)",
Color = OxyColor.FromRgb(0, 0, 255),
StrokeThickness = 2,
MarkerType = MarkerType.Circle,
MarkerSize = 4
};
_exhalationData = new List<DataPoint>();
_inhalationData = new List<DataPoint>();
_plotModel.Series.Add(_exhalationSeries);
_plotModel.Series.Add(_inhalationSeries);
// 添加轴标签
_plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "时间 (秒)" });
_plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Title = "流量 (单位)" });
// 在InitializePlot方法的轴配置中添加
_plotModel.Axes.Add(new LinearAxis
{
Position = AxisPosition.Bottom,
Title = "时间 (秒)",
IsZoomEnabled = false, // 禁用手动缩放
IsPanEnabled = false, // 禁用手动平移
MaximumPadding = 0.1, // 轴最大值留10%余量
MinimumPadding = 0.1 // 轴最小值留10%余量
});
// 添加图例
_plotModel.IsLegendVisible = true; // 设置图例可见
plotView.Model = _plotModel;
}
private void StartDataUpdate()
{
DispatcherTimer timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
timer.Tick += async (s, e) => await UpdateData();
timer.Start();
}
private async Task UpdateData()
{
if (!IsModbusConnected()) return;
try
{
// 读取寄存器值(保持不变)
ushort[] exhalationData = await Task.Run(() => _modbusMaster?.ReadHoldingRegisters(0x01, _OutBreathAddress, 2));
ushort[] inhalationData = await Task.Run(() => _modbusMaster?.ReadHoldingRegisters(0x01, _InBreathAddress, 2));
// 解析呼气流量(保持不变)
ushort a = exhalationData[0];
ushort b = exhalationData[1];
float floatValue = c.UshortToFloat(b, a);
floatValue = (float)Math.Round(floatValue, 2);
// 解析吸气流量(保持不变)
ushort a1 = inhalationData[0];
ushort b1 = inhalationData[1];
float floatValue1 = c.UshortToFloat(b1, a1);
floatValue1 = (float)Math.Round(floatValue1, 2);
double exhalationValue = floatValue;
double inhalationValue = floatValue1;
// 关键修改添加新数据后只保留最新的10个数据点
_exhalationData.Add(new DataPoint(_timeCounter, exhalationValue));
_inhalationData.Add(new DataPoint(_timeCounter, inhalationValue));
_timeCounter++; // 时间计数器统一递增(避免两条线时间轴不一致)
// 限制数据列表长度为10只保留最新数据
if (_exhalationData.Count > 10)
{
_exhalationData.RemoveRange(0, _exhalationData.Count - 10); // 移除旧数据
}
if (_inhalationData.Count > 10)
{
_inhalationData.RemoveRange(0, _inhalationData.Count - 10);
}
// 更新图表数据(保持不变)
_exhalationSeries.Points.Clear();
_inhalationSeries.Points.Clear();
foreach (var point in _exhalationData)
{
_exhalationSeries.Points.Add(point);
}
foreach (var point in _inhalationData)
{
_inhalationSeries.Points.Add(point);
}
_plotModel.InvalidatePlot(true);
}
catch (Exception ex)
{
Console.WriteLine($"读取数据失败: {ex.Message}");
}
}
/// <summary>
/// 初始化Modbus连接和定时器
/// </summary>
private void InitializeModbusTcp()
{
try
{
// 从配置读取PLC连接信息
string plcIp = ConfigurationManager.AppSettings["PLC2_IP"];
int plcPort = int.Parse(ConfigurationManager.AppSettings["PLC2_Port"]);
_tcpClient = new TcpClient(plcIp, plcPort);
_modbusMaster = ModbusIpMaster.CreateIp(_tcpClient);
_modbusMaster.Transport.ReadTimeout = 3000;
_modbusMaster.Transport.WriteTimeout = 3000;
fc = new Function(_modbusMaster);
// 初始化定时器
InitializeTimers();
// 初始化数据库
//InitializeDatabase();
}
catch (Exception ex)
{
ShowError($"Modbus初始化失败: {ex.Message}");
}
}
/// <summary>
/// 统一初始化所有定时器(避免重复配置)
/// </summary>
private void InitializeTimers()
{
_ReadTimer = CreateTimer(1000, OnRealTimerElapsed);
}
/// <summary>
///
/// </summary>
private void OnRealTimerElapsed(object sender, ElapsedEventArgs e)
{
ReadAndUpdateDualRegister(
_PositionAddress,
_PressAddress, _OutBreathAddress, _InBreathAddress,
(a, b, c, d) => UpdateTimerUI(a.ToString(), b.ToString(), c.ToString(), d.ToString())
);
}
/// <summary>
/// 更新呼吸计时UI
/// </summary>
private void UpdateTimerUI(string a, string b, string c, string d)
{
UpdateUiSafely(() =>
{
positionTxt.Text = IsModbusConnected() ? a : "连接断开";
pressTxt.Text = IsModbusConnected() ? b : "连接断开";
OutFowTxt.Text = IsModbusConnected() ? c : "连接断开";
InFlowTxt.Text = IsModbusConnected() ? d : "连接断开";
});
}
/// <summary>
/// 线程安全的UI更新通用方法统一实现
/// </summary>
private void UpdateUiSafely(Action action)
{
if (action == null) return;
if (Dispatcher.HasShutdownStarted)
{
return;
}
try
{
if (!Dispatcher.CheckAccess())
{
Dispatcher.Invoke(action, TimeSpan.FromSeconds(2));
}
else
{
action.Invoke();
}
}
catch (TaskCanceledException)
{
}
catch (Exception ex)
{
Console.WriteLine($"UI更新失败{ex.Message}");
}
}
/// <summary>
/// 读取两个寄存器并更新UI统一处理连接状态
/// </summary>
private void ReadAndUpdateDualRegister(ushort address1, ushort address2, ushort address3, ushort address4, Action<float, float, float, float> updateAction)
{
if (!IsModbusConnected())
{
updateAction?.Invoke(0, 0, 0, 0); // 触发UI显示"连接断开"
return;
}
try
{
ushort[] data1 = _modbusMaster?.ReadHoldingRegisters(0x01, address1, 2);
ushort[] data2 = _modbusMaster?.ReadHoldingRegisters(0x01, address2, 2);
ushort[] data3 = _modbusMaster?.ReadHoldingRegisters(0x01, address3, 2);
ushort[] data4 = _modbusMaster?.ReadHoldingRegisters(0x01, address4, 2);
// 2. 解析寄存器值data[0]是D312data[1]是D313
ushort a1 = data1[0]; // 高位寄存器值
ushort b1 = data1[1]; // 低位寄存器值
float floatValue1 = c.UshortToFloat(b1, a1);
floatValue1 = (float)Math.Round(floatValue1, 2);
// 2. 解析寄存器值data[0]是D312data[1]是D313
ushort a2 = data2[0]; // 高位寄存器值
ushort b2 = data2[1]; // 低位寄存器值
float floatValue2 = c.UshortToFloat(b2, a2);
floatValue2 = (float)Math.Round(floatValue2, 2);
// 2. 解析寄存器值data[0]是D312data[1]是D313
ushort a3 = data3[0]; // 高位寄存器值
ushort b3 = data3[1]; // 低位寄存器值
float floatValue3 = c.UshortToFloat(b3, a3);
floatValue3 = (float)Math.Round(floatValue3, 2);
// 2. 解析寄存器值data[0]是D312data[1]是D313
ushort a4 = data4[0]; // 高位寄存器值
ushort b4 = data4[1]; // 低位寄存器值
float floatValue4 = c.UshortToFloat(b4, a4);
floatValue4 = (float)Math.Round(floatValue4, 2);
updateAction?.Invoke(floatValue1, floatValue2, floatValue3, floatValue4);
}
catch (Exception ex)
{
Console.WriteLine($"读取寄存器[{address1:X4},{address2:X4}]失败: {ex.Message}");
updateAction?.Invoke(0, 0, 0, 0); // 触发UI显示"读取失败"
}
}
/// <summary>
/// 通用定时器创建方法(统一配置)
/// </summary>
private System.Timers.Timer CreateTimer(int intervalMs, ElapsedEventHandler elapsedAction)
{
var timer = new System.Timers.Timer(intervalMs)
{
AutoReset = true,
Enabled = true
};
timer.Elapsed += elapsedAction;
return timer;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
try
{
string imagePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources/sleep2.jpg");
if (System.IO.File.Exists(imagePath))
{
Background = new ImageBrush
{
ImageSource = new BitmapImage(new Uri(imagePath, UriKind.Absolute))
};
}
else
{
Console.WriteLine($"背景图片不存在: {imagePath}");
}
}
catch (Exception ex)
{
Console.WriteLine($"加载背景失败: {ex.Message}");
}
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
new Window5().ShowDialog();
Close();
}
private async Task WriteRegisterWithValidation(
TextBox inputControl,
ushort registerAddress,
float minValue,
float maxValue)
{
if (!IsModbusConnected())
{
ShowError("Modbus TCP 未连接");
return;
}
try
{
inputControl.Text = "操作中...";
Function ma = new Function(_modbusMaster);
ma.WriteToPLCForNew("", registerAddress, Function.DataType.);
//// 等待并刷新
//await Task.Delay(300);
//ReadAndUpdateRegister(registerAddress, true, v => UpdatePressureUI(v.ToString()));
}
catch (Exception ex)
{
ShowError($"操作失败: {ex.Message}");
}
finally
{
}
}
/// <summary>
/// 写入单个寄存器
/// </summary>
private async Task WriteSingleRegisterWithOutUI(
ushort registerAddress,
Func<int, string> successMessage)
{
if (!IsModbusConnected())
{
ShowError("Modbus TCP 未连接");
return;
}
try
{
await _modbusMaster.WriteSingleCoilAsync(0x01, registerAddress, true);
await Task.Delay(100); // 等待PLC处理
await _modbusMaster.WriteSingleCoilAsync(0x01, registerAddress, false);
await Task.Delay(100); // 等待PLC处理
//var data = _modbusMaster?.ReadHoldingRegisters(0x01, registerAddress, 1);
//if (data != null && data.Length > 0 && data[0] == 1)
//{
// ShowSuccess("写入成功,读取验证值为 1");
//}
//else
//{
// ShowSuccess("写入成功,但读取验证值异常,建议检查");
//}
}
catch (Exception ex)
{
ShowError($"设置失败: {ex.Message}");
}
finally
{
}
}
/// <summary>
/// 检查Modbus连接状态统一判断逻辑
/// </summary>
private bool IsModbusConnected()
{
return _modbusMaster != null && _tcpClient?.Connected == true;
}
// 消息提示封装(统一风格)
private void ShowSuccess(string message) => MessageBox.Show(message, "成功", MessageBoxButton.OK, MessageBoxImage.Information);
private void ShowWarning(string message) => MessageBox.Show(message, "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
private void ShowError(string message) => MessageBox.Show(message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
private void Button_Click_2(object sender, RoutedEventArgs e)
{
var mainWindow = MainWindow.Instance;
// 检查窗口状态只在窗口未显示时调用ShowDialog
if (!mainWindow.IsVisible)
{
mainWindow.ShowDialog();
}
else
{
// 如果窗口已显示,可将其激活到前台
mainWindow.Activate();
}
Close();
}
private void Button_Click_3(object sender, RoutedEventArgs e)
{
new ReportWindow5().ShowDialog();
Close();
}
private async void Button_Click_4(object sender, RoutedEventArgs e)
{
await WriteSingleRegisterWithOutUI(
registerAddress: _OutBreathUpAddress,
successMessage: value => $"呼上: {value}");
}
private async void Button_Click_5(object sender, RoutedEventArgs e)
{
await WriteSingleRegisterWithOutUI(
registerAddress: _OutBreathDownAddress,
successMessage: value => $"呼下: {value}");
}
private async void Button_Click_6(object sender, RoutedEventArgs e)
{
await WriteSingleRegisterWithOutUI(
registerAddress: _InBreathUpAddress,
successMessage: value => $"吸上: {value}");
}
private async void Button_Click_7(object sender, RoutedEventArgs e)
{
await WriteSingleRegisterWithOutUI(
registerAddress: _InBreathDownAddress,
successMessage: value => $"吸下: {value}");
}
private async void Button_Click_8(object sender, RoutedEventArgs e)
{
await WriteSingleRegisterWithOutUI(
registerAddress: _HandInBreathUpAddress,
successMessage: value => $"手动吸: {value}");
}
private async void Button_Click_9(object sender, RoutedEventArgs e)
{
await WriteSingleRegisterWithOutUI(
registerAddress: _HandInBreathDownAddress,
successMessage: value => $"手动呼: {value}");
}
private async void Button_Click_10(object sender, RoutedEventArgs e)
{
if (!IsModbusConnected())
{
UpdateResetButtonStatus("连接断开", Brushes.Red);
ShowError("Modbus TCP 未连接");
return;
}
try
{
UpdateResetButtonStatus("正在复位...", Brushes.LightGreen);
// 写入复位线圈
await Task.Run(() =>
_modbusMaster.WriteSingleCoil(0x01, _resetAddress, true)
);
fc.BtnClickFunctionForNew(Function.ButtonType., _resetAddress);
await Task.Delay(100);
// 写入复位线圈
await Task.Run(() =>
_modbusMaster.WriteSingleCoil(0x01, _resetAddress, false)
);
fc.BtnClickFunctionForNew(Function.ButtonType., _resetAddress);
UpdateResetButtonStatus("复位成功", Brushes.LightGreen);
}
catch (Exception ex)
{
Console.WriteLine($"复位异常: {ex.Message}");
UpdateResetButtonStatus("复位失败", Brushes.Red);
ShowError($"操作异常: {ex.Message}");
}
}
/// <summary>
/// 更新复位按钮状态UI
/// </summary>
private void UpdateResetButtonStatus(string text, Brush color)
{
UpdateUiSafely(() =>
{
ResetBtn.Content = text;
ResetBtn.Foreground = color;
});
}
private async void Button_Click_11(object sender, RoutedEventArgs e)
{
await WriteCoilWithCheck(
coilAddress: _BreathUpAddress,
value: true,
successMsg: "校准指令已被设备接收并执行(二次验证通过)",
failMsg: "校准执行超时,状态异常",
logMsg: "校准指令执行成功");
}
private async void Button_Click_12(object sender, RoutedEventArgs e)
{
await WriteCoilWithCheck(
coilAddress: _BreathDownAddress,
value: true,
successMsg: "校准指令已被设备接收并执行(二次验证通过)",
failMsg: "校准执行超时,状态异常",
logMsg: "校准指令执行成功"
);
}
private async void Button_Click_13(object sender, RoutedEventArgs e)
{
await WriteCoilWithCheck(
coilAddress: _PressCheckAddress,
value: true,
successMsg: "校准指令已被设备接收并执行(二次验证通过)",
failMsg: "校准执行超时,状态异常",
logMsg: "校准指令执行成功"
);
}
/// <summary>
/// 写入线圈并验证状态
/// </summary>
private async Task WriteCoilWithCheck(
ushort coilAddress,
bool value,
string successMsg,
string failMsg,
string logMsg)
{
if (!IsModbusConnected())
{
ShowError("Modbus TCP 未连接");
return;
}
try
{
// 写入线圈
await Task.Run(() =>
_modbusMaster.WriteSingleCoilAsync(0x01, coilAddress, value)
);
Thread.Sleep(200);
if (failMsg != null && (failMsg.Contains("停止") || failMsg.Contains("校准")))
{
// 写入线圈
await Task.Run(() =>
_modbusMaster.WriteSingleCoilAsync(0x01, coilAddress, false)
);
}
Thread.Sleep(100);
// 等待并验证
await Task.Delay(500);
bool[] status = await _modbusMaster?.ReadCoilsAsync(0x01, coilAddress, 1);
if (failMsg != null && !failMsg.Contains("停止") && !failMsg.Contains("校准"))
{
if (status[0] == value)
{
// 写入日志
WriteLog($"{logMsg} - 地址:{coilAddress},状态:{value}");
if (!string.IsNullOrEmpty(successMsg))
{
ShowSuccess(successMsg);
}
}
else
{
ShowError(failMsg);
}
}
}
catch (Exception ex)
{
ShowError($"通信错误: {ex.Message}");
}
}
/// <summary>
/// 日志路径
/// </summary>
private string logPath => System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "modbus_log.txt");
/// <summary>
/// 写入操作日志
/// </summary>
private void WriteLog(string content)
{
try
{
string log = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {content}\r\n";
System.IO.File.AppendAllText(logPath, log);
}
catch (Exception ex)
{
Console.WriteLine($"写入日志失败: {ex.Message}");
}
}
//public void Hertbean()
//{
// while (true)
// {
// try
// {
// if (!IsModbusConnected())
// { // 断线检测
// string plcIp = ConfigurationManager.AppSettings["PLC2_IP"];
// int plcPort = int.Parse(ConfigurationManager.AppSettings["PLC2_Port"]);
// _tcpClient = new TcpClient(plcIp, plcPort);
// _modbusMaster = ModbusIpMaster.CreateIp(_tcpClient);
// }
// // 执行读写操作(如 master.ReadHoldingRegisters
// Thread.Sleep(100); // 控制采集频率
// }
// catch (Exception ex)
// {
// Console.WriteLine($"断线/异常: {ex.Message},尝试重连...");
// _tcpClient.Close(); // 清理旧连接
// Thread.Sleep(1000); // 间隔重连
// }
// }
//}
private async void Button_Click_14(object sender, RoutedEventArgs e)
{
try
{
await WriteRegisterWithValidation(
inputControl: handmovementTxt,
registerAddress: _handSpeedAddress, // 手动速度寄存器地址(根据实际修改)
minValue: 1, // 手动速度最小值
maxValue: 1000 // 手动速度最大值
);
}
finally
{
}
}
private async void Button_Click_15(object sender, RoutedEventArgs e)
{
try
{
await WriteRegisterWithValidation(
inputControl: moistureTxt,
registerAddress: _moistureAddress, // 手动速度寄存器地址(根据实际修改)
minValue: 1, // 手动速度最小值
maxValue: 1000 // 手动速度最大值
);
}
finally
{
}
}
private async void Button_Click_16(object sender, RoutedEventArgs e)
{
try
{
await WriteRegisterWithValidation(
inputControl: OutFowRateTxt,
registerAddress: _OutFowRateAddress, // 手动速度寄存器地址(根据实际修改)
minValue: 1, // 手动速度最小值
maxValue: 1000 // 手动速度最大值
);
}
finally
{
}
}
private async void Button_Click_17(object sender, RoutedEventArgs e)
{
try
{
await WriteRegisterWithValidation(
inputControl: InFowRateTxt,
registerAddress: _InFowRateAddress, // 手动速度寄存器地址(根据实际修改)
minValue: 1, // 手动速度最小值
maxValue: 1000 // 手动速度最大值
);
}
finally
{
}
}
private async void Button_Click_18(object sender, RoutedEventArgs e)
{
try
{
await WriteRegisterWithValidation(
inputControl: PressRateTxt,
registerAddress: _PressRateAddress, // 手动速度寄存器地址(根据实际修改)
minValue: 1, // 手动速度最小值
maxValue: 1000 // 手动速度最大值
);
}
finally
{
}
}
}
}