This commit is contained in:
366
Window4.xaml.cs
366
Window4.xaml.cs
@@ -33,15 +33,13 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
private readonly ushort _modifiedNoseRegisterAddress = 0x0048; // 鼻口压力校准地址(M72)
|
||||
private readonly ushort _outRegisterAddress = 120; // 呼流量地址
|
||||
private readonly ushort _inRegisterAddress = 1400; // 吸流量地址
|
||||
private readonly ushort _flowRegisterAddress = 0x013C; // 呼气阻力记录(D136)
|
||||
private readonly ushort _flowInRegisterAddress = 0x013E; // 吸气阻力记录(D318)
|
||||
|
||||
|
||||
private readonly ushort _BreathOutRegisterAddress = 316; // 记录呼气阻力实时显示
|
||||
private readonly ushort _BreathInRegisterAddress = 318; // 记录吸气阻力实时显示
|
||||
|
||||
// 线圈地址(控制指令)
|
||||
private readonly ushort _testStartAddress = 0x0020; // 单一故障气阻测试启动(M32)
|
||||
private readonly ushort _testStopAddress = 0x0022; // 单一故障气阻测试停止(M34)
|
||||
|
||||
|
||||
#endregion
|
||||
@@ -116,16 +114,20 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
bool[] result = _modbusMaster?.ReadCoils(0x01, 33, 1);
|
||||
bool isTestRunning = result != null && result.Length > 0 && result[0];
|
||||
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
string running = lang == "en-US" ? "Test Running" : "测试启动成功";
|
||||
string ready = lang == "en-US" ? "Start Test" : "测试启动";
|
||||
|
||||
TestStartButton.Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (isTestRunning)
|
||||
{
|
||||
TestStartButton.Content = "测试启动成功";
|
||||
TestStartButton.Content = running;
|
||||
TestStartButton.Foreground = Brushes.LightGreen;
|
||||
}
|
||||
else
|
||||
{
|
||||
TestStartButton.Content = "测试启动";
|
||||
TestStartButton.Content = ready;
|
||||
TestStartButton.Foreground = Brushes.White;
|
||||
}
|
||||
});
|
||||
@@ -146,9 +148,9 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
|
||||
private void UpdateSettingUI2(string value)
|
||||
{
|
||||
UpdateUiSafely(() =>
|
||||
clostTxt.Text = IsModbusConnected() ? value : "连接断开"
|
||||
);
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
string disconnect = lang == "en-US" ? "Disconnected" : "连接断开";
|
||||
UpdateUiSafely(() => clostTxt.Text = IsModbusConnected() ? value : disconnect);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -286,9 +288,9 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private void UpdateOutUI(string value)
|
||||
{
|
||||
UpdateUiSafely(() =>
|
||||
outTxt.Text = IsModbusConnected() ? value : "连接断开"
|
||||
);
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
string disconnect = lang == "en-US" ? "Disconnected" : "连接断开";
|
||||
UpdateUiSafely(() => outTxt.Text = IsModbusConnected() ? value : disconnect);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -296,9 +298,9 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private void UpdateInUI(string value)
|
||||
{
|
||||
UpdateUiSafely(() =>
|
||||
InTxt.Text = IsModbusConnected() ? value : "连接断开"
|
||||
);
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
string disconnect = lang == "en-US" ? "Disconnected" : "连接断开";
|
||||
UpdateUiSafely(() => InTxt.Text = IsModbusConnected() ? value : disconnect);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -306,9 +308,9 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private void UpdateNoseUI(string value)
|
||||
{
|
||||
UpdateUiSafely(() =>
|
||||
NoseTxt.Text = IsModbusConnected() ? value : "连接断开"
|
||||
);
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
string disconnect = lang == "en-US" ? "Disconnected" : "连接断开";
|
||||
UpdateUiSafely(() => NoseTxt.Text = IsModbusConnected() ? value : disconnect);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -379,13 +381,12 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private async void Button_Click_1(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await WriteCoilWithCheck(
|
||||
coilAddress: _modifiedNoseRegisterAddress,
|
||||
value: true,
|
||||
successMsg: "校准指令已被设备接收并执行(二次验证通过)",
|
||||
failMsg: "校准执行超时,状态异常",
|
||||
logMsg: "校准指令执行成功"
|
||||
);
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
string success = lang == "en-US" ? "Calibration OK (verified)" : "校准指令已被设备接收并执行(二次验证通过)";
|
||||
string fail = lang == "en-US" ? "Calibration timeout" : "校准执行超时,状态异常";
|
||||
string log = lang == "en-US" ? "Calibration done" : "校准指令执行成功";
|
||||
|
||||
await WriteCoilWithCheck(_modifiedNoseRegisterAddress, true, success, fail, log);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -393,15 +394,13 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private async void Button_Click_3(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await WriteCoilWithCheck(
|
||||
coilAddress: 0x0022, // M34
|
||||
value: true,
|
||||
successMsg: null, // 无弹窗,仅日志
|
||||
failMsg: "单一故障气阻测试停止超时,状态异常",
|
||||
logMsg: "单一故障气阻测试停止"
|
||||
);
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
string fail = lang == "en-US" ? "Test stop timeout" : "单一故障气阻测试停止超时,状态异常";
|
||||
string log = lang == "en-US" ? "Test stopped" : "单一故障气阻测试停止";
|
||||
string start = lang == "en-US" ? "Start Test" : "测试启动";
|
||||
|
||||
TestStartButton.Content = "测试启动";
|
||||
await WriteCoilWithCheck(0x0022, true, null, fail, log);
|
||||
TestStartButton.Content = start;
|
||||
TestStartButton.Foreground = Brushes.White;
|
||||
}
|
||||
|
||||
@@ -410,39 +409,28 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private async void Button_Click_4(object sender, RoutedEventArgs e)
|
||||
{
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
UpdateButtonStatus("连接断开", Brushes.Red);
|
||||
ShowError("Modbus TCP 未连接");
|
||||
UpdateButtonStatus(lang == "en-US" ? "Disconnected" : "连接断开", Brushes.Red);
|
||||
ShowError(lang == "en-US" ? "Modbus TCP not connected" : "Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
UpdateButtonStatus("正在启动...", Brushes.LightGreen);
|
||||
|
||||
// 写入启动线圈
|
||||
await Task.Run(() =>
|
||||
_modbusMaster.WriteSingleCoilAsync(0x01, _testStartAddress, true)
|
||||
);
|
||||
|
||||
// 等待并验证状态
|
||||
UpdateButtonStatus(lang == "en-US" ? "Starting..." : "正在启动...", Brushes.LightGreen);
|
||||
await Task.Run(() => _modbusMaster.WriteSingleCoilAsync(0x01, _testStartAddress, true));
|
||||
await Task.Delay(100);
|
||||
// 写入启动线圈
|
||||
await Task.Run(() =>
|
||||
_modbusMaster.WriteSingleCoilAsync(0x01, _testStartAddress, false)
|
||||
);
|
||||
|
||||
// 等待并验证状态
|
||||
await Task.Run(() => _modbusMaster.WriteSingleCoilAsync(0x01, _testStartAddress, false));
|
||||
await Task.Delay(100);
|
||||
UpdateButtonStatus("测试启动成功", Brushes.LightGreen);
|
||||
|
||||
UpdateButtonStatus(lang == "en-US" ? "Test Started" : "测试启动成功", Brushes.LightGreen);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"测试启动异常: {ex.Message}");
|
||||
UpdateButtonStatus("测试启动失败", Brushes.Red);
|
||||
ShowError($"操作异常: {ex.Message}");
|
||||
UpdateButtonStatus(lang == "en-US" ? "Start Failed" : "测试启动失败", Brushes.Red);
|
||||
ShowError(lang == "en-US" ? $"Error: {ex.Message}" : $"操作异常: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,35 +439,21 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private async void Button_Click_5(object sender, RoutedEventArgs e)
|
||||
{
|
||||
//await ReadAndSaveRegister(
|
||||
// address: _flowRegisterAddress,
|
||||
// address2: _flowInRegisterAddress,
|
||||
// control: saveFlowOutTxt,
|
||||
// isFlow: true
|
||||
//);
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
saveFlowOutTxt.Text = "连接断开";
|
||||
ShowError("Modbus TCP 未连接");
|
||||
saveFlowOutTxt.Text = lang == "en-US" ? "Disconnected" : "连接断开";
|
||||
ShowError(lang == "en-US" ? "Modbus TCP not connected" : "Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fc.BtnClickFunctionForNew(Function.ButtonType.切换型, 192);
|
||||
fc.BtnClickFunctionForNew(Function.ButtonType.切换型, 192);
|
||||
|
||||
ReadAndUpdateRegister(
|
||||
_BreathOutRegisterAddress, true,
|
||||
value => UpdateFlowFlowUI(value.ToString())
|
||||
);
|
||||
ReadAndUpdateRegister(_BreathOutRegisterAddress, true, value => UpdateFlowFlowUI(value.ToString()));
|
||||
ReadAndUpdateRegister(_BreathInRegisterAddress, true, value => UpdateCloseFlowUI2(value.ToString()));
|
||||
|
||||
ReadAndUpdateRegister(
|
||||
_BreathInRegisterAddress, true,
|
||||
value => UpdateCloseFlowUI2(value.ToString())
|
||||
);
|
||||
|
||||
// 尝试将文本框内容转换为float
|
||||
if (float.TryParse(saveFlowOutTxt.Text, out float flowValue) &&
|
||||
float.TryParse(saveFlowInTxt.Text, out float pressureValue))
|
||||
{
|
||||
@@ -487,35 +461,28 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
}
|
||||
else
|
||||
{
|
||||
// 转换失败,提示错误信息
|
||||
ShowError("流量或压力值格式不正确,请检查输入");
|
||||
ShowError(lang == "en-US" ? "Invalid data format" : "流量或压力值格式不正确,请检查输入");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 步骤2:读取CO2表数据
|
||||
List<CO2Record> co2Records = ReadCO2RecordsFromDatabase();
|
||||
if (co2Records == null || !co2Records.Any())
|
||||
List<CO2Record> records = ReadCO2RecordsFromDatabase();
|
||||
if (records == null || records.Count == 0)
|
||||
{
|
||||
MessageBox.Show("单一故障气阻表中无数据,无法导出", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
string msg = lang == "en-US" ? "No data to export" : "单一故障气阻表中无数据,无法导出";
|
||||
MessageBox.Show(msg, "Info", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// 步骤3:导出Excel
|
||||
bool exportSuccess = ExportCO2RecordsToExcel(co2Records);
|
||||
bool exportSuccess = ExportCO2RecordsToExcel(records);
|
||||
if (exportSuccess)
|
||||
{
|
||||
MessageBox.Show("数据已成功导出到Excel", "成功", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
string msg = lang == "en-US" ? "Export successful" : "数据已成功导出到Excel";
|
||||
MessageBox.Show(msg, "Success", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Excel导出失败,请检查文件是否被占用", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
string msg = lang == "en-US" ? "Export failed" : "Excel导出失败,请检查文件是否被占用";
|
||||
MessageBox.Show(msg, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -523,65 +490,45 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
{
|
||||
try
|
||||
{
|
||||
// WPF 原生保存对话框(替代 WinForms)
|
||||
|
||||
SaveFileDialog saveDialog = new SaveFileDialog
|
||||
{
|
||||
Filter = "Excel文件 (*.xlsx)|*.xlsx",
|
||||
FileName = $"单一故障气阻记录_{DateTime.Now:yyyyMMddHHmmss}.xlsx",
|
||||
Title = "保存单一故障气阻记录"
|
||||
Filter = "Excel(*.xlsx)|*.xlsx",
|
||||
FileName = $"AirResistance_{DateTime.Now:yyyyMMddHHmmss}.xlsx",
|
||||
Title = "Export Air Resistance Data"
|
||||
};
|
||||
|
||||
// 用户取消选择则返回
|
||||
bool? result = saveDialog.ShowDialog(); if (!(result ?? false)) return false;
|
||||
|
||||
if (saveDialog.ShowDialog() != true) return false;
|
||||
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
|
||||
|
||||
// EPPlus 许可设置(.NET 8 必须显式设置)
|
||||
ExcelPackage.LicenseContext = LicenseContext.NonCommercial; // 非商业用途
|
||||
|
||||
// 创建并写入Excel
|
||||
using (ExcelPackage package = new ExcelPackage(new FileInfo(saveDialog.FileName)))
|
||||
using (var package = new ExcelPackage(new FileInfo(saveDialog.FileName)))
|
||||
{
|
||||
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("单一故障气阻记录");
|
||||
var ws = package.Workbook.Worksheets.Add("Records");
|
||||
ws.Cells[1, 1].Value = "Expiratory Pa";
|
||||
ws.Cells[1, 2].Value = "Inspiratory Pa";
|
||||
ws.Cells[1, 3].Value = "Time";
|
||||
|
||||
// 表头(对应DataGrid列)
|
||||
worksheet.Cells[1, 1].Value = "呼气阻力pa";
|
||||
worksheet.Cells[1, 2].Value = "吸气阻力pa";
|
||||
worksheet.Cells[1, 3].Value = "时间";
|
||||
|
||||
// 表头样式(加粗、居中)
|
||||
using (var headerRange = worksheet.Cells[1, 1, 1, 6])
|
||||
{
|
||||
headerRange.Style.Font.Bold = true;
|
||||
headerRange.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
|
||||
}
|
||||
|
||||
// 填充数据(从第2行开始)
|
||||
for (int i = 0; i < records.Count; i++)
|
||||
{
|
||||
int row = i + 2;
|
||||
var record = records[i];
|
||||
worksheet.Cells[row, 1].Value = record.Flow;
|
||||
worksheet.Cells[row, 2].Value = record.Pressure;
|
||||
worksheet.Cells[row, 3].Value = record.RecordTime.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
ws.Cells[i + 2, 1].Value = records[i].Flow;
|
||||
ws.Cells[i + 2, 2].Value = records[i].Pressure;
|
||||
ws.Cells[i + 2, 3].Value = records[i].RecordTime.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
|
||||
// 自动调整列宽
|
||||
worksheet.Cells.AutoFitColumns();
|
||||
|
||||
// 保存文件
|
||||
ws.Cells.AutoFitColumns();
|
||||
package.Save();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"导出失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
string err = lang == "en-US" ? "Export failed" : "导出失败";
|
||||
MessageBox.Show($"{err}: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
@@ -623,15 +570,15 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
|
||||
private void UpdateFlowFlowUI(string value)
|
||||
{
|
||||
UpdateUiSafely(() =>
|
||||
saveFlowOutTxt.Text = IsModbusConnected() ? value : "连接断开"
|
||||
);
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
string disconnect = lang == "en-US" ? "Disconnected" : "连接断开";
|
||||
UpdateUiSafely(() => saveFlowOutTxt.Text = IsModbusConnected() ? value : disconnect);
|
||||
}
|
||||
private void UpdateCloseFlowUI2(string value)
|
||||
{
|
||||
UpdateUiSafely(() =>
|
||||
saveFlowInTxt.Text = IsModbusConnected() ? value : "连接断开"
|
||||
);
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
string disconnect = lang == "en-US" ? "Disconnected" : "连接断开";
|
||||
UpdateUiSafely(() => saveFlowInTxt.Text = IsModbusConnected() ? value : disconnect);
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
@@ -678,39 +625,38 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
|
||||
#region 通用操作方法(提取重复逻辑)
|
||||
private async Task WriteRegisterWithValidation(
|
||||
TextBox inputControl,
|
||||
ushort registerAddress,
|
||||
float minValue,
|
||||
float maxValue)
|
||||
TextBox inputControl,
|
||||
ushort registerAddress,
|
||||
float minValue,
|
||||
float maxValue)
|
||||
{
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
ShowError("Modbus TCP 未连接");
|
||||
ShowError(lang == "en-US" ? "Modbus TCP not connected" : "Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
// 输入验证
|
||||
if (!float.TryParse(inputControl.Text.Trim(), out float value) ||
|
||||
value < minValue || value > maxValue)
|
||||
if (!float.TryParse(inputControl.Text.Trim(), out float value) || value < minValue || value > maxValue)
|
||||
{
|
||||
ShowWarning($"请输入{minValue}~{maxValue}的数字");
|
||||
string msg = lang == "en-US" ? $"Enter {minValue}~{maxValue}" : $"请输入{minValue}~{maxValue}的数字";
|
||||
ShowWarning(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
inputControl.Text = "操作中...";
|
||||
|
||||
inputControl.Text = lang == "en-US" ? "Processing..." : "操作中...";
|
||||
Function ma = new Function(_modbusMaster);
|
||||
ma.WriteToPLCForNew(value.ToString(), registerAddress, Function.DataType.浮点型);
|
||||
|
||||
// 等待并刷新
|
||||
await Task.Delay(300);
|
||||
ReadAndUpdateRegister(registerAddress, true, v => UpdatePressureUI(v.ToString()));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError($"操作失败: {ex.Message}");
|
||||
string err = lang == "en-US" ? $"Failed: {ex.Message}" : $"操作失败: {ex.Message}";
|
||||
ShowError(err);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -733,6 +679,8 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
string failMsg,
|
||||
string logMsg)
|
||||
{
|
||||
string lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
InitializeModbusTcp();
|
||||
@@ -746,7 +694,19 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
_modbusMaster.WriteSingleCoilAsync(0x01, coilAddress, value)
|
||||
);
|
||||
Thread.Sleep(200);
|
||||
if (failMsg != null && (failMsg.Contains("停止") || failMsg.Contains("校准")))
|
||||
|
||||
// ==============================
|
||||
// 兼容:中文 停止/校准 + 英文 Stop/Calib
|
||||
// ==============================
|
||||
bool needReset = false;
|
||||
if (failMsg != null)
|
||||
{
|
||||
bool hasStop = failMsg.Contains("停止") || failMsg.Contains("Stop") || failMsg.Contains("stop");
|
||||
bool hasCalib = failMsg.Contains("校准") || failMsg.Contains("Calib") || failMsg.Contains("calib");
|
||||
needReset = hasStop || hasCalib;
|
||||
}
|
||||
|
||||
if (failMsg != null && needReset)
|
||||
{
|
||||
// 写入线圈
|
||||
await Task.Run(() =>
|
||||
@@ -756,15 +716,24 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
|
||||
Thread.Sleep(100);
|
||||
|
||||
|
||||
// 等待并验证
|
||||
await Task.Delay(500);
|
||||
bool[] status = await _modbusMaster?.ReadCoilsAsync(0x01, coilAddress, 1);
|
||||
|
||||
|
||||
if (failMsg != null && !failMsg.Contains("停止") && !failMsg.Contains("校准"))
|
||||
// ==============================
|
||||
// 同样兼容中英文判断
|
||||
// ==============================
|
||||
bool noResetCheck = false;
|
||||
if (failMsg != null)
|
||||
{
|
||||
if (status[0] == value)
|
||||
bool hasStop = failMsg.Contains("停止") || failMsg.Contains("Stop") || failMsg.Contains("stop");
|
||||
bool hasCalib = failMsg.Contains("校准") || failMsg.Contains("Calib") || failMsg.Contains("calib");
|
||||
noResetCheck = !hasStop && !hasCalib;
|
||||
}
|
||||
|
||||
if (failMsg != null && noResetCheck)
|
||||
{
|
||||
if (status != null && status.Length > 0 && status[0] == value)
|
||||
{
|
||||
// 写入日志
|
||||
WriteLog($"{logMsg} - 地址:{coilAddress},状态:{value}");
|
||||
@@ -781,92 +750,11 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError($"通信错误: {ex.Message}");
|
||||
ShowError(lang == "en-US" ? $"Communication error: {ex.Message}" : $"通信错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取寄存器并刷新UI
|
||||
/// </summary>
|
||||
private async Task RefreshRegister(ushort address, TextBox control)
|
||||
{
|
||||
try
|
||||
{
|
||||
ushort[] data = await Task.Run(() =>
|
||||
_modbusMaster?.ReadHoldingRegisters(0x01, address, 1)
|
||||
);
|
||||
control.Text = data[0].ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"刷新寄存器失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取线圈状态
|
||||
/// </summary>
|
||||
private async Task<bool> ReadCoilStatus(ushort address)
|
||||
{
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
bool[] status = _modbusMaster?.ReadCoils(0x01, address, 1);
|
||||
return status[0];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"读取线圈状态失败: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取寄存器并保存到数据库
|
||||
/// </summary>
|
||||
private async Task ReadAndSaveRegister(ushort address, ushort address2, TextBox control, bool isFlow)
|
||||
{
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
control.Text = "连接断开";
|
||||
ShowError("Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
control.Text = "读取中...";
|
||||
|
||||
// 读取寄存器
|
||||
ushort[] data = await Task.Run(() =>
|
||||
_modbusMaster?.ReadHoldingRegisters(0x01, address, 1)
|
||||
);
|
||||
|
||||
double value = data[0];
|
||||
control.Text = value.ToString("0.00");
|
||||
|
||||
|
||||
saveFlowInTxt.Text = "读取中...";
|
||||
|
||||
// 读取寄存器
|
||||
ushort[] data2 = await Task.Run(() =>
|
||||
_modbusMaster?.ReadHoldingRegisters(0x01, address2, 1)
|
||||
);
|
||||
|
||||
double value2 = data2[0];
|
||||
saveFlowInTxt.Text = value2.ToString("0.00");
|
||||
|
||||
// 保存到数据库(呼气阻力存Flow,吸气阻力存Pressure)
|
||||
SaveRecordToDatabase(value, value2);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
control.Text = "读取失败";
|
||||
ShowError($"读取失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 数据库与日志操作
|
||||
@@ -998,10 +886,6 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
e.Handled = !isNumber;
|
||||
}
|
||||
|
||||
private void RefreshClosePressure()
|
||||
{
|
||||
ReadAndUpdateRegister(_pressureSettingRegisterAddress, true, v => UpdateClosePressureUI(v.ToString()));
|
||||
}
|
||||
|
||||
private void UpdateClosePressureUI(string value)
|
||||
{
|
||||
@@ -1031,10 +915,12 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
switch (content)
|
||||
{
|
||||
case "呼气":
|
||||
await WriteCoilWithCheck(36, false, null, "呼吸类别", "呼吸类别");
|
||||
case "Exhale":
|
||||
await WriteCoilWithCheck(36, false, null, "Breath Type", "Breath Type");
|
||||
break;
|
||||
case "吸气":
|
||||
await WriteCoilWithCheck(36, true, null, "呼吸类别", "呼吸类别");
|
||||
case "Inhale":
|
||||
await WriteCoilWithCheck(36, true, null, "Breath Type", "Breath Type");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
||||
597
Window5.xaml.cs
597
Window5.xaml.cs
@@ -206,55 +206,57 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
|
||||
private void OnStartTimerElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
try
|
||||
{
|
||||
bool[] result = _modbusMaster?.ReadCoils(0x01, 98, 1);
|
||||
bool isTestRunning = result != null && result.Length > 0 && result[0];
|
||||
bool isRunning = result != null && result.Length > 0 && result[0];
|
||||
|
||||
TestStartButton.Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (isTestRunning)
|
||||
if (isRunning)
|
||||
{
|
||||
TestStartButton.Content = "测试启动成功";
|
||||
TestStartButton.Content = _lang == "en-US" ? "Test Started" : "测试启动成功";
|
||||
TestStartButton.Foreground = Brushes.LightGreen;
|
||||
}
|
||||
else
|
||||
{
|
||||
TestStartButton.Content = "测试启动";
|
||||
TestStartButton.Content = _lang == "en-US" ? "Start Test" : "测试启动";
|
||||
TestStartButton.Foreground = Brushes.White;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"读取线圈或更新UI失败:{ex.Message}");
|
||||
Console.WriteLine(_lang == "en-US" ? $"Failed to read coil: {ex.Message}" : $"读取线圈或更新UI失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnResetTimerElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
try
|
||||
{
|
||||
bool[] result = _modbusMaster?.ReadCoils(0x01, 3, 1);
|
||||
bool isTestRunning = result != null && result.Length > 0 && result[0];
|
||||
bool isRunning = result != null && result.Length > 0 && result[0];
|
||||
|
||||
ResetBtn.Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (isTestRunning)
|
||||
if (isRunning)
|
||||
{
|
||||
ResetBtn.Content = "复位成功";
|
||||
ResetBtn.Content = _lang == "en-US" ? "Reset Success" : "复位成功";
|
||||
ResetBtn.Foreground = Brushes.LightGreen;
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetBtn.Content = "复位";
|
||||
ResetBtn.Content = _lang == "en-US" ? "Reset" : "复位";
|
||||
ResetBtn.Foreground = Brushes.White;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"读取线圈或更新UI失败:{ex.Message}");
|
||||
Console.WriteLine(_lang == "en-US" ? $"Failed to read coil: {ex.Message}" : $"读取线圈或更新UI失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,125 +267,67 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
|
||||
private void OnbreathTimerElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
try
|
||||
{
|
||||
// 读取线圈状态
|
||||
bool[] inhaleResult = _modbusMaster?.ReadCoils(0x01, 51, 1);
|
||||
bool[] exhaleResult = _modbusMaster?.ReadCoils(0x01, 55, 1);
|
||||
bool[] inhale = _modbusMaster?.ReadCoils(0x01, 51, 1);
|
||||
bool[] exhale = _modbusMaster?.ReadCoils(0x01, 55, 1);
|
||||
bool isIn = inhale != null && inhale.Length > 0 && inhale[0];
|
||||
bool isEx = exhale != null && exhale.Length > 0 && exhale[0];
|
||||
|
||||
bool isInhale = inhaleResult != null && inhaleResult.Length > 0 && inhaleResult[0];
|
||||
bool isExhale = exhaleResult != null && exhaleResult.Length > 0 && exhaleResult[0];
|
||||
|
||||
// 确定新状态(先判断异常,再判断正常状态)
|
||||
string newState;
|
||||
if (isInhale && isExhale || !isInhale && !isExhale)
|
||||
{
|
||||
newState = "异常";
|
||||
}
|
||||
else if (isInhale)
|
||||
{
|
||||
newState = "吸气";
|
||||
}
|
||||
else // isExhale
|
||||
{
|
||||
newState = "呼气";
|
||||
}
|
||||
if ((isIn && isEx) || (!isIn && !isEx))
|
||||
newState = _lang == "en-US" ? "Error" : "异常";
|
||||
else if (isIn)
|
||||
newState = _lang == "en-US" ? "Inhale" : "吸气";
|
||||
else
|
||||
newState = _lang == "en-US" ? "Exhale" : "呼气";
|
||||
|
||||
// 关键:仅当新状态与当前状态不同时,才更新UI(避免重复触发)
|
||||
if (newState != _currentBreathState)
|
||||
{
|
||||
breathType.Dispatcher.Invoke(() =>
|
||||
{
|
||||
// 更新当前状态记录
|
||||
_currentBreathState = newState;
|
||||
|
||||
if (newState == "异常")
|
||||
if (newState == (_lang == "en-US" ? "Error" : "异常"))
|
||||
{
|
||||
breathType.Text = "待机";
|
||||
// 停止所有动画,避免异常状态下动画混乱
|
||||
breathType.Text = _lang == "en-US" ? "Standby" : "待机";
|
||||
StopAllAnimations();
|
||||
breathType.Foreground = new SolidColorBrush(Colors.Orange);
|
||||
breathType.Foreground = Brushes.Orange;
|
||||
breathType.FontSize = 20;
|
||||
breathType.Opacity = 1.0;
|
||||
}
|
||||
else if (newState == "吸气")
|
||||
else if (newState == (_lang == "en-US" ? "Inhale" : "吸气"))
|
||||
{
|
||||
breathType.Text = "吸气";
|
||||
|
||||
// 停止现有动画(避免与新动画冲突)
|
||||
breathType.Text = _lang == "en-US" ? "Inhale" : "吸气";
|
||||
StopAllAnimations();
|
||||
|
||||
// 颜色动画
|
||||
ColorAnimation colorAnimation = new ColorAnimation
|
||||
{
|
||||
From = Colors.Gray,
|
||||
To = Colors.Green,
|
||||
Duration = TimeSpan.FromSeconds(2.5)
|
||||
};
|
||||
SolidColorBrush colorBrush = new SolidColorBrush(Colors.Gray);
|
||||
breathType.Foreground = colorBrush;
|
||||
colorBrush.BeginAnimation(SolidColorBrush.ColorProperty, colorAnimation);
|
||||
|
||||
// 大小动画
|
||||
DoubleAnimation sizeAnimation = new DoubleAnimation
|
||||
{
|
||||
From = 16,
|
||||
To = 40,
|
||||
Duration = TimeSpan.FromSeconds(2.5)
|
||||
};
|
||||
breathType.BeginAnimation(TextBlock.FontSizeProperty, sizeAnimation);
|
||||
|
||||
// 透明度动画
|
||||
DoubleAnimation opacityAnimation = new DoubleAnimation
|
||||
{
|
||||
From = 0.5,
|
||||
To = 1.0,
|
||||
Duration = TimeSpan.FromSeconds(2.5)
|
||||
};
|
||||
breathType.BeginAnimation(TextBlock.OpacityProperty, opacityAnimation);
|
||||
var colorAnim = new ColorAnimation(Colors.Gray, Colors.Green, TimeSpan.FromSeconds(2.5));
|
||||
var brush = new SolidColorBrush(Colors.Gray);
|
||||
breathType.Foreground = brush;
|
||||
brush.BeginAnimation(SolidColorBrush.ColorProperty, colorAnim);
|
||||
var sizeAnim = new DoubleAnimation(16, 40, TimeSpan.FromSeconds(2.5));
|
||||
var opacAnim = new DoubleAnimation(0.5, 1.0, TimeSpan.FromSeconds(2.5));
|
||||
breathType.BeginAnimation(TextBlock.FontSizeProperty, sizeAnim);
|
||||
breathType.BeginAnimation(TextBlock.OpacityProperty, opacAnim);
|
||||
}
|
||||
else // 呼气
|
||||
else
|
||||
{
|
||||
breathType.Text = "呼气";
|
||||
|
||||
// 停止现有动画
|
||||
breathType.Text = _lang == "en-US" ? "Exhale" : "呼气";
|
||||
StopAllAnimations();
|
||||
|
||||
// 颜色动画
|
||||
ColorAnimation colorAnimation = new ColorAnimation
|
||||
{
|
||||
From = Colors.Green,
|
||||
To = Colors.Red,
|
||||
Duration = TimeSpan.FromSeconds(2.5)
|
||||
};
|
||||
SolidColorBrush colorBrush = new SolidColorBrush(Colors.Green);
|
||||
breathType.Foreground = colorBrush;
|
||||
colorBrush.BeginAnimation(SolidColorBrush.ColorProperty, colorAnimation);
|
||||
|
||||
// 大小动画
|
||||
DoubleAnimation sizeAnimation = new DoubleAnimation
|
||||
{
|
||||
From = 40,
|
||||
To = 16,
|
||||
Duration = TimeSpan.FromSeconds(2.5)
|
||||
};
|
||||
breathType.BeginAnimation(TextBlock.FontSizeProperty, sizeAnimation);
|
||||
|
||||
// 透明度动画
|
||||
DoubleAnimation opacityAnimation = new DoubleAnimation
|
||||
{
|
||||
From = 1.0,
|
||||
To = 0.5,
|
||||
Duration = TimeSpan.FromSeconds(2.5)
|
||||
};
|
||||
breathType.BeginAnimation(TextBlock.OpacityProperty, opacityAnimation);
|
||||
var colorAnim = new ColorAnimation(Colors.Green, Colors.Red, TimeSpan.FromSeconds(2.5));
|
||||
var brush = new SolidColorBrush(Colors.Green);
|
||||
breathType.Foreground = brush;
|
||||
brush.BeginAnimation(SolidColorBrush.ColorProperty, colorAnim);
|
||||
var sizeAnim = new DoubleAnimation(40, 16, TimeSpan.FromSeconds(2.5));
|
||||
var opacAnim = new DoubleAnimation(1.0, 0.5, TimeSpan.FromSeconds(2.5));
|
||||
breathType.BeginAnimation(TextBlock.FontSizeProperty, sizeAnim);
|
||||
breathType.BeginAnimation(TextBlock.OpacityProperty, opacAnim);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"读取线圈或更新UI失败:{ex.Message}");
|
||||
Console.WriteLine(_lang == "en-US" ? $"Failed to read coil: {ex.Message}" : $"读取线圈或更新UI失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -749,25 +693,62 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
#endregion
|
||||
|
||||
#region UI更新(统一线程安全处理)
|
||||
/// <summary>
|
||||
/// 更新呼吸次数UI
|
||||
/// </summary>
|
||||
private void UpdateOutUI(string value)
|
||||
|
||||
|
||||
|
||||
private void UpdateConnectionTextUI(System.Windows.Controls.TextBox textBox, string value)
|
||||
{
|
||||
// 获取当前语言(默认中文)
|
||||
string currentLanguage = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
|
||||
// 多语言提示信息
|
||||
string disconnectMsg = currentLanguage == "en-US" ? "Connection disconnected" : "连接断开";
|
||||
|
||||
// 安全更新UI
|
||||
UpdateUiSafely(() =>
|
||||
respiratoryCountTxt.Text = IsModbusConnected() ? value : "连接断开"
|
||||
textBox.Text = IsModbusConnected() ? value : disconnectMsg
|
||||
);
|
||||
}
|
||||
|
||||
private void UpdateConnectionTextUI(System.Windows.Controls.TextBlock textBox, string value)
|
||||
{
|
||||
// 获取当前语言(默认中文)
|
||||
string currentLanguage = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
|
||||
// 多语言提示信息
|
||||
string disconnectMsg = currentLanguage == "en-US" ? "Connection disconnected" : "连接断开";
|
||||
|
||||
// 安全更新UI
|
||||
UpdateUiSafely(() =>
|
||||
textBox.Text = IsModbusConnected() ? value : disconnectMsg
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private void UpdateOutUI(string val)
|
||||
{
|
||||
string currentLanguage = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
UpdateUiSafely(() => respiratoryCountTxt.Text = IsModbusConnected() ? val : (currentLanguage == "en-US" ? "Disconnected" : "连接断开"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 更新呼吸计时UI
|
||||
/// </summary>
|
||||
private void UpdateTimerUI(string minute, string second)
|
||||
{
|
||||
string currentLanguage = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
UpdateUiSafely(() =>
|
||||
{
|
||||
breathTimeBegin.Text = IsModbusConnected() ? minute : "连接断开";
|
||||
breathTimeEnd.Text = IsModbusConnected() ? second : "连接断开";
|
||||
breathTimeBegin.Text = IsModbusConnected() ? minute : (currentLanguage == "en-US" ? "Disconnected" : "连接断开");
|
||||
breathTimeEnd.Text = IsModbusConnected() ? second : (currentLanguage == "en-US" ? "Disconnected" : "连接断开");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -776,10 +757,11 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private void UpdateCo2TimerUI(string pressure, string co2)
|
||||
{
|
||||
string currentLanguage = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
UpdateUiSafely(() =>
|
||||
{
|
||||
RespiratoryPressureTxt.Text = IsModbusConnected() ? pressure : "连接断开";
|
||||
CO2PressureTxt.Text = IsModbusConnected() ? co2 : "连接断开";
|
||||
RespiratoryPressureTxt.Text = IsModbusConnected() ? pressure : (currentLanguage == "en-US" ? "Disconnected" : "连接断开");
|
||||
CO2PressureTxt.Text = IsModbusConnected() ? co2 : (currentLanguage == "en-US" ? "Disconnected" : "连接断开");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -788,10 +770,11 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private void UpdateCO2BeginEndTimerUI(string begin, string end)
|
||||
{
|
||||
string currentLanguage = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
UpdateUiSafely(() =>
|
||||
{
|
||||
CO2BeginTb.Text = IsModbusConnected() ? begin : "连接断开";
|
||||
CO2EndTb.Text = IsModbusConnected() ? end : "连接断开";
|
||||
CO2BeginTb.Text = IsModbusConnected() ? begin : (currentLanguage == "en-US" ? "Disconnected" : "连接断开");
|
||||
CO2EndTb.Text = IsModbusConnected() ? end : (currentLanguage == "en-US" ? "Disconnected" : "连接断开");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -800,22 +783,12 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private void UpdateCO2AddTimerUI(string value)
|
||||
{
|
||||
string currentLanguage = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
UpdateUiSafely(() =>
|
||||
CO2AddTxt.Text = IsModbusConnected() ? value : "连接断开"
|
||||
CO2AddTxt.Text = IsModbusConnected() ? value : (currentLanguage == "en-US" ? "Disconnected" : "连接断开")
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新流量压力UI(按钮写入后刷新)
|
||||
/// </summary>
|
||||
private void UpdateFlowPressureUI(string value, string value2)
|
||||
{
|
||||
UpdateUiSafely(() =>
|
||||
{
|
||||
OutTxt.Text = value;
|
||||
InTxt.Text = value2;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新潮气UI(按钮写入后刷新)
|
||||
@@ -952,41 +925,28 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private async void Button_Click_10(object sender, RoutedEventArgs e)
|
||||
{
|
||||
string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
UpdateResetButtonStatus("连接断开", Brushes.Red);
|
||||
ShowError("Modbus TCP 未连接");
|
||||
UpdateResetButtonStatus(_lang == "en-US" ? "Disconnected" : "连接断开", Brushes.Red);
|
||||
ShowError(_lang == "en-US" ? "Modbus TCP not connected" : "Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
UpdateResetButtonStatus("正在复位...", Brushes.LightGreen);
|
||||
|
||||
// 写入复位线圈
|
||||
await Task.Run(() =>
|
||||
_modbusMaster.WriteSingleCoil(0x01, _resetAddress, true)
|
||||
);
|
||||
|
||||
UpdateResetButtonStatus(_lang == "en-US" ? "Resetting..." : "正在复位...", 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)
|
||||
);
|
||||
|
||||
|
||||
await Task.Run(() => _modbusMaster.WriteSingleCoil(0x01, _resetAddress, false));
|
||||
fc.BtnClickFunctionForNew(Function.ButtonType.复位型, _resetAddress);
|
||||
|
||||
|
||||
UpdateResetButtonStatus("复位成功", Brushes.LightGreen);
|
||||
|
||||
UpdateResetButtonStatus(_lang == "en-US" ? "Reset Success" : "复位成功", Brushes.LightGreen);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"复位异常: {ex.Message}");
|
||||
UpdateResetButtonStatus("复位失败", Brushes.Red);
|
||||
ShowError($"操作异常: {ex.Message}");
|
||||
Console.WriteLine(_lang == "en-US" ? $"Reset error: {ex.Message}" : $"复位异常: {ex.Message}");
|
||||
UpdateResetButtonStatus(_lang == "en-US" ? "Reset Failed" : "复位失败", Brushes.Red);
|
||||
ShowError(_lang == "en-US" ? $"Operation error: {ex.Message}" : $"操作异常: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -995,16 +955,17 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private async void Button_Click_11(object sender, RoutedEventArgs e)
|
||||
{
|
||||
string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
UpdateButtonStatus("连接断开", Brushes.Red);
|
||||
ShowError("Modbus TCP 未连接");
|
||||
UpdateButtonStatus(_lang == "en-US" ? "Disconnected" : "连接断开", Brushes.Red);
|
||||
ShowError(_lang == "en-US" ? "Modbus TCP not connected" : "Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
UpdateButtonStatus("正在启动...", Brushes.LightGreen);
|
||||
UpdateButtonStatus(_lang == "en-US" ? "Starting..." : "正在启动...", Brushes.LightGreen);
|
||||
|
||||
// 写入启动线圈
|
||||
await Task.Run(() =>
|
||||
@@ -1020,12 +981,12 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
|
||||
// 等待并验证状态
|
||||
await Task.Delay(200);
|
||||
UpdateButtonStatus("测试启动成功", Brushes.LightGreen);
|
||||
UpdateButtonStatus(_lang == "en-US" ? "Test Start Success" : "测试启动成功", Brushes.LightGreen);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"测试启动异常: {ex.Message}");
|
||||
UpdateButtonStatus("测试启动失败", Brushes.Red);
|
||||
UpdateButtonStatus(_lang == "en-US" ? "Test Start Failed" : "测试启动失败", Brushes.Red);
|
||||
ShowError($"操作异常: {ex.Message}");
|
||||
}
|
||||
}
|
||||
@@ -1035,15 +996,9 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private async void Button_Click_12(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await WriteCoilWithCheck(
|
||||
coilAddress: _testStopAddress, // M8(统一使用常量地址)
|
||||
value: true,
|
||||
successMsg: null,
|
||||
failMsg: "测试停止超时,状态异常",
|
||||
logMsg: "测试停止"
|
||||
);
|
||||
|
||||
TestStartButton.Content = "测试启动";
|
||||
string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
await WriteCoilWithCheck(_testStopAddress, true, null, _lang == "en-US" ? "Test stop timeout" : "测试停止超时,状态异常", _lang == "en-US" ? "Test Stop" : "测试停止");
|
||||
TestStartButton.Content = _lang == "en-US" ? "Start Test" : "测试启动";
|
||||
TestStartButton.Foreground = Brushes.White;
|
||||
}
|
||||
|
||||
@@ -1052,85 +1007,52 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private async void Button_Click_13(object sender, RoutedEventArgs e)
|
||||
{
|
||||
string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
ShowError("Modbus TCP 未连接");
|
||||
ShowError(_lang == "en-US" ? "Modbus TCP not connected" : "Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Delay(100);
|
||||
fc.BtnClickFunctionForNew(Function.ButtonType.切换型, 63);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError($"操作异常: {ex.Message}");
|
||||
}
|
||||
|
||||
|
||||
ShowWarning("已开始记录");
|
||||
// 创建并启动数据记录定时器(1秒间隔)
|
||||
try { await Task.Delay(100); fc.BtnClickFunctionForNew(Function.ButtonType.切换型, 63); }
|
||||
catch (Exception ex) { ShowError(_lang == "en-US" ? $"Operation error: {ex.Message}" : $"操作异常: {ex.Message}"); }
|
||||
ShowWarning(_lang == "en-US" ? "Recording started" : "已开始记录");
|
||||
_beginRecordTimer = CreateTimer(1000, OnBeginRecordTimerElapsed);
|
||||
}
|
||||
|
||||
private async void Button_Click_14(object sender, RoutedEventArgs e)
|
||||
{
|
||||
|
||||
string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
ShowError("Modbus TCP 未连接");
|
||||
ShowError(_lang == "en-US" ? "Modbus TCP not connected" : "Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
try { await Task.Delay(100); fc.BtnClickFunctionForNew(Function.ButtonType.切换型, 64); }
|
||||
catch (Exception ex) { ShowError(_lang == "en-US" ? $"Operation error: {ex.Message}" : $"操作异常: {ex.Message}"); }
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Delay(100);
|
||||
fc.BtnClickFunctionForNew(Function.ButtonType.切换型, 64);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError($"操作异常: {ex.Message}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 步骤1:停止定时器并释放资源
|
||||
if (_beginRecordTimer != null)
|
||||
{
|
||||
MessageBox.Show("已停止记录", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
_beginRecordTimer.Stop();
|
||||
_beginRecordTimer.Dispose();
|
||||
_beginRecordTimer = null;
|
||||
MessageBox.Show(_lang == "en-US" ? "Recording stopped" : "已停止记录", _lang == "en-US" ? "Info" : "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
_beginRecordTimer.Stop(); _beginRecordTimer.Dispose(); _beginRecordTimer = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("未在记录状态,无需停止", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
MessageBox.Show(_lang == "en-US" ? "Not recording" : "未在记录状态,无需停止", _lang == "en-US" ? "Warning" : "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// 步骤2:读取CO2表数据
|
||||
List<CO2Record> co2Records = ReadCO2RecordsFromDatabase();
|
||||
if (co2Records == null || !co2Records.Any())
|
||||
var records = ReadCO2RecordsFromDatabase();
|
||||
if (records == null || !records.Any())
|
||||
{
|
||||
MessageBox.Show("CO2表中无数据,无法导出", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
MessageBox.Show(_lang == "en-US" ? "No CO2 data to export" : "CO2表中无数据,无法导出", _lang == "en-US" ? "Warning" : "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// 步骤3:导出Excel
|
||||
bool exportSuccess = ExportCO2RecordsToExcel(co2Records);
|
||||
if (exportSuccess)
|
||||
{
|
||||
MessageBox.Show("数据已成功导出到Excel", "成功", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Excel导出失败,请检查文件是否被占用", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
bool ok = ExportCO2RecordsToExcel(records);
|
||||
if (ok) MessageBox.Show(_lang == "en-US" ? "Export to Excel success" : "数据已成功导出到Excel", _lang == "en-US" ? "Success" : "成功", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
else MessageBox.Show(_lang == "en-US" ? "Export failed" : "Excel导出失败,请检查文件是否被占用", _lang == "en-US" ? "Error" : "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 从数据库CO2表读取数据(不变)
|
||||
/// </summary>
|
||||
@@ -1177,69 +1099,41 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private bool ExportCO2RecordsToExcel(List<CO2Record> records)
|
||||
{
|
||||
string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
try
|
||||
{
|
||||
// WPF 原生保存对话框(替代 WinForms)
|
||||
|
||||
SaveFileDialog saveDialog = new SaveFileDialog
|
||||
SaveFileDialog dlg = new SaveFileDialog
|
||||
{
|
||||
Filter = "Excel文件 (*.xlsx)|*.xlsx",
|
||||
FileName = $"CO2记录_{DateTime.Now:yyyyMMddHHmmss}.xlsx",
|
||||
Title = "保存CO2记录"
|
||||
Filter = _lang == "en-US" ? "Excel File (*.xlsx)|*.xlsx" : "Excel文件 (*.xlsx)|*.xlsx",
|
||||
FileName = $"CO2_Record_{DateTime.Now:yyyyMMddHHmmss}.xlsx",
|
||||
Title = _lang == "en-US" ? "Save CO2 Record" : "保存CO2记录"
|
||||
};
|
||||
|
||||
// 用户取消选择则返回
|
||||
bool? result = saveDialog.ShowDialog(); if (!(result ?? false)) return false;
|
||||
|
||||
|
||||
// EPPlus 许可设置(.NET 8 必须显式设置)
|
||||
ExcelPackage.LicenseContext = LicenseContext.NonCommercial; // 非商业用途
|
||||
|
||||
// 创建并写入Excel
|
||||
using (ExcelPackage package = new ExcelPackage(new FileInfo(saveDialog.FileName)))
|
||||
if (dlg.ShowDialog() != true) return false;
|
||||
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
|
||||
using (var pkg = new ExcelPackage(new FileInfo(dlg.FileName)))
|
||||
{
|
||||
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("CO2记录");
|
||||
|
||||
// 表头(对应DataGrid列)
|
||||
worksheet.Cells[1, 1].Value = "二氧化碳浓度(%)";
|
||||
worksheet.Cells[1, 2].Value = "压力(pa)";
|
||||
worksheet.Cells[1, 3].Value = "开始CO2浓度(%)";
|
||||
worksheet.Cells[1, 4].Value = "终CO2浓度(%)";
|
||||
worksheet.Cells[1, 5].Value = "CO2浓度相对增加(%)";
|
||||
worksheet.Cells[1, 6].Value = "时间";
|
||||
|
||||
// 表头样式(加粗、居中)
|
||||
using (var headerRange = worksheet.Cells[1, 1, 1, 6])
|
||||
{
|
||||
headerRange.Style.Font.Bold = true;
|
||||
headerRange.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
|
||||
}
|
||||
|
||||
// 填充数据(从第2行开始)
|
||||
var ws = pkg.Workbook.Worksheets.Add(_lang == "en-US" ? "CO2 Records" : "CO2记录");
|
||||
ws.Cells[1, 1].Value = _lang == "en-US" ? "CO2(%)" : "二氧化碳浓度(%)";
|
||||
ws.Cells[1, 2].Value = _lang == "en-US" ? "Pressure(Pa)" : "压力(pa)";
|
||||
ws.Cells[1, 3].Value = _lang == "en-US" ? "Begin CO2(%)" : "开始CO2浓度(%)";
|
||||
ws.Cells[1, 4].Value = _lang == "en-US" ? "End CO2(%)" : "终CO2浓度(%)";
|
||||
ws.Cells[1, 5].Value = _lang == "en-US" ? "CO2 Added(%)" : "CO2浓度相对增加(%)";
|
||||
ws.Cells[1, 6].Value = _lang == "en-US" ? "Time" : "时间";
|
||||
var head = ws.Cells[1, 1, 1, 6]; head.Style.Font.Bold = true; head.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
|
||||
for (int i = 0; i < records.Count; i++)
|
||||
{
|
||||
int row = i + 2;
|
||||
var record = records[i];
|
||||
worksheet.Cells[row, 1].Value = record.Flow;
|
||||
worksheet.Cells[row, 2].Value = record.Pressure;
|
||||
worksheet.Cells[row, 3].Value = record.BeginCO2;
|
||||
worksheet.Cells[row, 4].Value = record.EndCO2;
|
||||
worksheet.Cells[row, 5].Value = record.CO2Added;
|
||||
worksheet.Cells[row, 6].Value = record.RecordTime.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
var row = i + 2; var r = records[i];
|
||||
ws.Cells[row, 1].Value = r.Flow; ws.Cells[row, 2].Value = r.Pressure;
|
||||
ws.Cells[row, 3].Value = r.BeginCO2; ws.Cells[row, 4].Value = r.EndCO2;
|
||||
ws.Cells[row, 5].Value = r.CO2Added; ws.Cells[row, 6].Value = r.RecordTime.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
|
||||
// 自动调整列宽
|
||||
worksheet.Cells.AutoFitColumns();
|
||||
|
||||
// 保存文件
|
||||
package.Save();
|
||||
ws.Cells.AutoFitColumns(); pkg.Save();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"导出失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
MessageBox.Show(_lang == "en-US" ? $"Export failed: {ex.Message}" : $"导出失败:{ex.Message}", _lang == "en-US" ? "Error" : "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1265,64 +1159,49 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// <summary>
|
||||
/// 写入线圈并验证状态(通用方法)
|
||||
/// </summary>
|
||||
private async Task WriteCoilWithCheck(
|
||||
ushort coilAddress,
|
||||
bool value,
|
||||
string successMsg,
|
||||
string failMsg,
|
||||
string logMsg)
|
||||
private async Task WriteCoilWithCheck(ushort coilAddress, bool value, string successMsg, string failMsg, string logMsg)
|
||||
{
|
||||
string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
ShowError("Modbus TCP 未连接");
|
||||
ShowError(_lang == "en-US" ? "Modbus TCP not connected" : "Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 写入线圈
|
||||
await Task.Run(() =>
|
||||
_modbusMaster?.WriteSingleCoilAsync(0x01, coilAddress, value)
|
||||
);
|
||||
await Task.Run(() => _modbusMaster?.WriteSingleCoilAsync(0x01, coilAddress, value));
|
||||
Thread.Sleep(200);
|
||||
if (failMsg != null && (failMsg.Contains("停止") || failMsg.Contains("校准")))
|
||||
bool needReset = false;
|
||||
if (failMsg != null)
|
||||
{
|
||||
// 写入线圈
|
||||
await Task.Run(() =>
|
||||
_modbusMaster?.WriteSingleCoilAsync(0x01, coilAddress, false)
|
||||
);
|
||||
bool stop = failMsg.Contains("停止") || failMsg.Contains("Stop") || failMsg.Contains("stop");
|
||||
bool calib = failMsg.Contains("校准") || failMsg.Contains("Calib") || failMsg.Contains("calib");
|
||||
needReset = stop || calib;
|
||||
}
|
||||
|
||||
Thread.Sleep(200);
|
||||
|
||||
|
||||
// 等待并验证
|
||||
if (needReset)
|
||||
{
|
||||
await Task.Run(() => _modbusMaster?.WriteSingleCoilAsync(0x01, coilAddress, false));
|
||||
}
|
||||
Thread.Sleep(100);
|
||||
await Task.Delay(500);
|
||||
bool[] status = await _modbusMaster?.ReadCoilsAsync(0x01, coilAddress, 1);
|
||||
|
||||
if (status != null)
|
||||
bool noReset = false;
|
||||
if (failMsg != null)
|
||||
{
|
||||
if (failMsg != null && !failMsg.Contains("停止") && !failMsg.Contains("校准"))
|
||||
{
|
||||
if (status[0] == value)
|
||||
{
|
||||
// 写入日志
|
||||
WriteLog($"{logMsg} - 地址:{coilAddress},状态:{value}");
|
||||
if (!string.IsNullOrEmpty(successMsg))
|
||||
{
|
||||
ShowSuccess(successMsg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowError(failMsg);
|
||||
}
|
||||
}
|
||||
bool stop = failMsg.Contains("停止") || failMsg.Contains("Stop") || failMsg.Contains("stop");
|
||||
bool calib = failMsg.Contains("校准") || failMsg.Contains("Calib") || failMsg.Contains("calib");
|
||||
noReset = !stop && !calib;
|
||||
}
|
||||
if (noReset && status != null && status.Length > 0 && status[0] == value)
|
||||
{
|
||||
WriteLog($"{logMsg} - Address: {coilAddress}, State: {value}");
|
||||
if (!string.IsNullOrEmpty(successMsg)) ShowSuccess(successMsg);
|
||||
}
|
||||
else if (noReset) ShowError(failMsg);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError($"通信错误: {ex.Message}");
|
||||
ShowError(_lang == "en-US" ? $"Communication error: {ex.Message}" : $"通信错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1452,42 +1331,18 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
#endregion
|
||||
|
||||
|
||||
private async Task WriteRegisterWithValidation(
|
||||
TextBox inputControl,
|
||||
ushort registerAddress,
|
||||
float minValue,
|
||||
float maxValue)
|
||||
private async Task WriteRegisterWithValidation(TextBox inputControl, ushort registerAddress, float minValue, float maxValue)
|
||||
{
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
ShowError("Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
if (!IsModbusConnected()) { ShowError(_lang == "en-US" ? "Modbus TCP not connected" : "Modbus TCP 未连接"); return; }
|
||||
try
|
||||
{
|
||||
inputControl.Text = "操作中...";
|
||||
|
||||
inputControl.Text = _lang == "en-US" ? "Processing..." : "操作中...";
|
||||
Function ma = new Function(_modbusMaster);
|
||||
ma.WriteToPLCForNew("", registerAddress, Function.DataType.浮点型);
|
||||
|
||||
// 等待并刷新
|
||||
await Task.Delay(300);
|
||||
//ReadAndUpdateSingleRegister(342, true, v => UpdatePressureUI1(v.ToString()));
|
||||
//ReadAndUpdateSingleRegister(registerAddress, true, v => UpdatePressureUI1(v.ToString()));
|
||||
//ReadAndUpdateSingleRegister(registerAddress, true, v => UpdatePressureUI1(v.ToString()));
|
||||
//ReadAndUpdateSingleRegister(registerAddress, true, v => UpdatePressureUI1(v.ToString()));
|
||||
//ReadAndUpdateSingleRegister(registerAddress, true, v => UpdatePressureUI1(v.ToString()));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError($"操作失败: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
}
|
||||
catch (Exception ex) { ShowError(_lang == "en-US" ? $"Operation failed: {ex.Message}" : $"操作失败: {ex.Message}"); }
|
||||
}
|
||||
|
||||
|
||||
@@ -1515,51 +1370,30 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private async Task StartPressurizeLoop()
|
||||
{
|
||||
// 检查Modbus连接
|
||||
string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
UpdateAddButtonStatus("连接断开", Brushes.Red);
|
||||
ShowError("Modbus TCP 未连接");
|
||||
_isPressurizing = false; // 重置状态
|
||||
return;
|
||||
UpdateAddButtonStatus(_lang == "en-US" ? "Disconnected" : "连接断开", Brushes.Red);
|
||||
ShowError(_lang == "en-US" ? "Modbus TCP not connected" : "Modbus TCP 未连接");
|
||||
_isPressurizing = false; return;
|
||||
}
|
||||
|
||||
// 初始化取消令牌(用于安全停止循环)
|
||||
_pressurizeCts = new CancellationTokenSource();
|
||||
var token = _pressurizeCts.Token;
|
||||
|
||||
_pressurizeCts = new CancellationTokenSource(); var token = _pressurizeCts.Token;
|
||||
try
|
||||
{
|
||||
UpdateAddButtonStatus("正在加压...", Brushes.LightGreen);
|
||||
|
||||
// 异步循环:持续执行加压操作,直到状态为停止或被取消
|
||||
UpdateAddButtonStatus(_lang == "en-US" ? "Pressurizing..." : "正在加压...", Brushes.LightGreen);
|
||||
while (_isPressurizing && !token.IsCancellationRequested)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
_modbusMaster.WriteSingleCoilAsync(0x01, 657, true)
|
||||
);
|
||||
|
||||
await Task.Run(() => _modbusMaster.WriteSingleCoilAsync(0x01, 657, true));
|
||||
await Task.Delay(200);
|
||||
|
||||
|
||||
// 循环中再次检查连接(防止中途断开)
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
throw new Exception("Modbus连接中途断开");
|
||||
}
|
||||
}
|
||||
|
||||
// 正常停止时更新状态
|
||||
if (!token.IsCancellationRequested)
|
||||
{
|
||||
UpdateAddButtonStatus("加压", Brushes.White);
|
||||
if (!IsModbusConnected()) throw new Exception(_lang == "en-US" ? "Modbus disconnected" : "Modbus连接中途断开");
|
||||
}
|
||||
if (!token.IsCancellationRequested) UpdateAddButtonStatus(_lang == "en-US" ? "Pressurize" : "加压", Brushes.White);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"加压异常: {ex.Message}");
|
||||
UpdateAddButtonStatus("加压失败", Brushes.Red);
|
||||
ShowError($"操作异常: {ex.Message}");
|
||||
Console.WriteLine(_lang == "en-US" ? $"Pressurize error: {ex.Message}" : $"加压异常: {ex.Message}");
|
||||
UpdateAddButtonStatus(_lang == "en-US" ? "Press Failed" : "加压失败", Brushes.Red);
|
||||
ShowError(_lang == "en-US" ? $"Operation error: {ex.Message}" : $"操作异常: {ex.Message}");
|
||||
_isPressurizing = false;
|
||||
}
|
||||
}
|
||||
@@ -1570,33 +1404,16 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
private void StopPressurize()
|
||||
{
|
||||
// 取消循环令牌
|
||||
if (_pressurizeCts != null && !_pressurizeCts.IsCancellationRequested)
|
||||
{
|
||||
_pressurizeCts.Cancel();
|
||||
_pressurizeCts.Dispose(); // 释放资源
|
||||
}
|
||||
|
||||
// 复位状态和显示
|
||||
string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
if (_pressurizeCts != null && !_pressurizeCts.IsCancellationRequested) { _pressurizeCts.Cancel(); _pressurizeCts.Dispose(); }
|
||||
_isPressurizing = false;
|
||||
UpdateAddButtonStatus("加压", Brushes.White);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
if (IsModbusConnected())
|
||||
{
|
||||
_modbusMaster.WriteSingleCoilAsync(0x01, 657, false).Wait();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"停止时复位线圈失败: {ex.Message}");
|
||||
}
|
||||
UpdateAddButtonStatus(_lang == "en-US" ? "Pressurize" : "加压", Brushes.White);
|
||||
try { if (IsModbusConnected()) _modbusMaster.WriteSingleCoilAsync(0x01, 657, false).Wait(); } catch { }
|
||||
}
|
||||
|
||||
private async void Button_Click_17(object sender, RoutedEventArgs e)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
// 验证并写入呼吸比-呼气值
|
||||
|
||||
279
Window6.xaml.cs
279
Window6.xaml.cs
@@ -30,6 +30,7 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
public partial class Window6 : Window
|
||||
{
|
||||
private readonly string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
DataChange c = new DataChange();
|
||||
#region 寄存器/线圈地址定义(按功能分组,标注物理意义)
|
||||
// 控制线圈(M代码)
|
||||
@@ -132,19 +133,19 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
{
|
||||
if (isTestRunning)
|
||||
{
|
||||
ResetBtn.Content = "复位成功";
|
||||
ResetBtn.Content = _lang == "en-US" ? "Reset Success" : "复位成功";
|
||||
ResetBtn.Foreground = Brushes.LightGreen;
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetBtn.Content = "复位";
|
||||
ResetBtn.Content = _lang == "en-US" ? "Reset" : "复位";
|
||||
ResetBtn.Foreground = Brushes.White;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"读取线圈或更新UI失败:{ex.Message}");
|
||||
Console.WriteLine(_lang == "en-US" ? $"Read coil failed: {ex.Message}" : $"读取线圈或更新UI失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,21 +227,18 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
{
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
updateAction("离线");
|
||||
updateAction(_lang == "en-US" ? "Offline" : "离线");
|
||||
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]; // 整数
|
||||
object value = isFloat ? Convert.ToSingle(c.UshortToFloat(data[1], data[0])) : data[0];
|
||||
updateAction(value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
updateAction("读取失败");
|
||||
updateAction(_lang == "en-US" ? "Read Failed" : "读取失败");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,22 +257,22 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
{
|
||||
_plotModel = new PlotModel
|
||||
{
|
||||
Title = "呼气流量与吸气流量",
|
||||
Background = OxyColor.FromRgb(240, 240, 240) // 设置背景色
|
||||
Title = _lang == "en-US" ? "Exhalation & Inhalation Flow" : "呼气流量与吸气流量",
|
||||
Background = OxyColor.FromRgb(240, 240, 240)
|
||||
};
|
||||
|
||||
_exhalationSeries = new LineSeries
|
||||
{
|
||||
Title = "呼气流量 (D5016)",
|
||||
Title = _lang == "en-US" ? "Exhalation Flow (D5016)" : "呼气流量 (D5016)",
|
||||
Color = OxyColor.FromRgb(255, 0, 0),
|
||||
StrokeThickness = 2, // 设置线条宽度
|
||||
MarkerType = MarkerType.Circle, // 添加标记
|
||||
StrokeThickness = 2,
|
||||
MarkerType = MarkerType.Circle,
|
||||
MarkerSize = 4
|
||||
};
|
||||
|
||||
_inhalationSeries = new LineSeries
|
||||
{
|
||||
Title = "吸气流量 (D5014)",
|
||||
Title = _lang == "en-US" ? "Inhalation Flow (D5014)" : "吸气流量 (D5014)",
|
||||
Color = OxyColor.FromRgb(0, 0, 255),
|
||||
StrokeThickness = 2,
|
||||
MarkerType = MarkerType.Circle,
|
||||
@@ -287,30 +285,16 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
_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; // 设置图例可见
|
||||
_plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = _lang == "en-US" ? "Time (s)" : "时间 (秒)" });
|
||||
_plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Title = _lang == "en-US" ? "Flow" : "流量" });
|
||||
|
||||
_plotModel.IsLegendVisible = true;
|
||||
plotView.Model = _plotModel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void StartDataUpdate()
|
||||
{
|
||||
DispatcherTimer timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
|
||||
@@ -435,10 +419,10 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
{
|
||||
UpdateUiSafely(() =>
|
||||
{
|
||||
positionTxt.Text = IsModbusConnected() ? a : "连接断开";
|
||||
pressTxt.Text = IsModbusConnected() ? b : "连接断开";
|
||||
OutFowTxt.Text = IsModbusConnected() ? c : "连接断开";
|
||||
InFlowTxt.Text = IsModbusConnected() ? d : "连接断开";
|
||||
positionTxt.Text = IsModbusConnected() ? a : (_lang == "en-US" ? "Disconnected" : "连接断开");
|
||||
pressTxt.Text = IsModbusConnected() ? b : (_lang == "en-US" ? "Disconnected" : "连接断开");
|
||||
OutFowTxt.Text = IsModbusConnected() ? c : (_lang == "en-US" ? "Disconnected" : "连接断开");
|
||||
InFlowTxt.Text = IsModbusConnected() ? d : (_lang == "en-US" ? "Disconnected" : "连接断开");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -602,11 +586,10 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
inputControl.Text = _lang == "en-US" ? "Processing..." : "操作中...";
|
||||
|
||||
try
|
||||
{
|
||||
inputControl.Text = "操作中...";
|
||||
|
||||
Function ma = new Function(_modbusMaster);
|
||||
ma.WriteToPLCForNew("", registerAddress, Function.DataType.浮点型);
|
||||
@@ -634,7 +617,7 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
{
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
ShowError("Modbus TCP 未连接");
|
||||
// ShowError("Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
try
|
||||
@@ -645,19 +628,10 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
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}");
|
||||
ShowError(_lang == "en-US" ? $"Set failed: {ex.Message}" : $"设置失败: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -673,10 +647,10 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
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 ShowSuccess(string msg) => MessageBox.Show(msg, _lang == "en-US" ? "Success" : "成功", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
private void ShowWarning(string msg) => MessageBox.Show(msg, _lang == "en-US" ? "Warning" : "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
private void ShowError(string msg) => MessageBox.Show(msg, _lang == "en-US" ? "Error" : "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -710,86 +684,36 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
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_4(object sender, RoutedEventArgs e) => await WriteSingleRegisterWithOutUI(_OutBreathUpAddress, v => $"Exhale Up: {v}");
|
||||
private async void Button_Click_5(object sender, RoutedEventArgs e) => await WriteSingleRegisterWithOutUI(_OutBreathDownAddress, v => $"Exhale Down: {v}");
|
||||
private async void Button_Click_6(object sender, RoutedEventArgs e) => await WriteSingleRegisterWithOutUI(_InBreathUpAddress, v => $"Inhale Up: {v}");
|
||||
private async void Button_Click_7(object sender, RoutedEventArgs e) => await WriteSingleRegisterWithOutUI(_InBreathDownAddress, v => $"Inhale Down: {v}");
|
||||
private async void Button_Click_8(object sender, RoutedEventArgs e) => await WriteSingleRegisterWithOutUI(_HandInBreathUpAddress, v => $"Manual Inhale: {v}");
|
||||
private async void Button_Click_9(object sender, RoutedEventArgs e) => await WriteSingleRegisterWithOutUI(_HandInBreathDownAddress, v => $"Manual Exhale: {v}");
|
||||
|
||||
private async void Button_Click_10(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
UpdateResetButtonStatus("连接断开", Brushes.Red);
|
||||
ShowError("Modbus TCP 未连接");
|
||||
UpdateResetButtonStatus(_lang == "en-US" ? "Disconnected" : "连接断开", Brushes.Red);
|
||||
ShowError(_lang == "en-US" ? "Modbus TCP not connected" : "Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
UpdateResetButtonStatus("正在复位...", Brushes.LightGreen);
|
||||
|
||||
// 写入复位线圈
|
||||
await Task.Run(() =>
|
||||
_modbusMaster.WriteSingleCoil(0x01, _resetAddress, true)
|
||||
);
|
||||
|
||||
UpdateResetButtonStatus(_lang == "en-US" ? "Resetting..." : "正在复位...", 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)
|
||||
);
|
||||
|
||||
|
||||
await Task.Run(() => _modbusMaster.WriteSingleCoil(0x01, _resetAddress, false));
|
||||
fc.BtnClickFunctionForNew(Function.ButtonType.复位型, _resetAddress);
|
||||
|
||||
|
||||
UpdateResetButtonStatus("复位成功", Brushes.LightGreen);
|
||||
|
||||
UpdateResetButtonStatus(_lang == "en-US" ? "Reset Success" : "复位成功", Brushes.LightGreen);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"复位异常: {ex.Message}");
|
||||
UpdateResetButtonStatus("复位失败", Brushes.Red);
|
||||
ShowError($"操作异常: {ex.Message}");
|
||||
Console.WriteLine(_lang == "en-US" ? $"Reset error: {ex.Message}" : $"复位异常: {ex.Message}");
|
||||
UpdateResetButtonStatus(_lang == "en-US" ? "Reset Failed" : "复位失败", Brushes.Red);
|
||||
ShowError(_lang == "en-US" ? $"Operation error: {ex.Message}" : $"操作异常: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -807,96 +731,49 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
|
||||
private async void Button_Click_11(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await WriteCoilWithCheck(
|
||||
coilAddress: _BreathUpAddress,
|
||||
value: true,
|
||||
successMsg: "校准指令已被设备接收并执行(二次验证通过)",
|
||||
failMsg: "校准执行超时,状态异常",
|
||||
logMsg: "校准指令执行成功");
|
||||
await WriteCoilWithCheck(_BreathUpAddress, true,
|
||||
_lang == "en-US" ? "Calibration success" : "校准指令已被设备接收并执行",
|
||||
_lang == "en-US" ? "Calibration timeout" : "校准执行超时,状态异常",
|
||||
_lang == "en-US" ? "Calibration executed" : "校准指令执行成功");
|
||||
}
|
||||
|
||||
|
||||
private async void Button_Click_12(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await WriteCoilWithCheck(
|
||||
coilAddress: _BreathDownAddress,
|
||||
value: true,
|
||||
successMsg: "校准指令已被设备接收并执行(二次验证通过)",
|
||||
failMsg: "校准执行超时,状态异常",
|
||||
logMsg: "校准指令执行成功"
|
||||
);
|
||||
await WriteCoilWithCheck(_BreathDownAddress, true,
|
||||
_lang == "en-US" ? "Calibration success" : "校准指令已被设备接收并执行",
|
||||
_lang == "en-US" ? "Calibration timeout" : "校准执行超时,状态异常",
|
||||
_lang == "en-US" ? "Calibration executed" : "校准指令执行成功");
|
||||
}
|
||||
|
||||
private async void Button_Click_13(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await WriteCoilWithCheck(
|
||||
coilAddress: _PressCheckAddress,
|
||||
value: true,
|
||||
successMsg: "校准指令已被设备接收并执行(二次验证通过)",
|
||||
failMsg: "校准执行超时,状态异常",
|
||||
logMsg: "校准指令执行成功"
|
||||
);
|
||||
await WriteCoilWithCheck(_PressCheckAddress, true,
|
||||
_lang == "en-US" ? "Calibration success" : "校准指令已被设备接收并执行",
|
||||
_lang == "en-US" ? "Calibration timeout" : "校准执行超时,状态异常",
|
||||
_lang == "en-US" ? "Calibration executed" : "校准指令执行成功");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 写入线圈并验证状态
|
||||
/// </summary>
|
||||
private async Task WriteCoilWithCheck(
|
||||
ushort coilAddress,
|
||||
bool value,
|
||||
string successMsg,
|
||||
string failMsg,
|
||||
string logMsg)
|
||||
{
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
ShowError("Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
private async Task WriteCoilWithCheck(ushort coil, bool val, string ok, string err, string log)
|
||||
{
|
||||
if (!IsModbusConnected()) { ShowError(_lang == "en-US" ? "Modbus TCP not connected" : "Modbus TCP 未连接"); return; }
|
||||
try
|
||||
{
|
||||
// 写入线圈
|
||||
await Task.Run(() =>
|
||||
_modbusMaster.WriteSingleCoilAsync(0x01, coilAddress, value)
|
||||
);
|
||||
await Task.Run(() => _modbusMaster.WriteSingleCoilAsync(0x01, coil, val));
|
||||
Thread.Sleep(200);
|
||||
if (failMsg != null && (failMsg.Contains("停止") || failMsg.Contains("校准")))
|
||||
{
|
||||
// 写入线圈
|
||||
await Task.Run(() =>
|
||||
_modbusMaster.WriteSingleCoilAsync(0x01, coilAddress, false)
|
||||
);
|
||||
}
|
||||
|
||||
if (err.Contains("Calib") || err.Contains("校准")) await Task.Run(() => _modbusMaster.WriteSingleCoilAsync(0x01, coil, 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}");
|
||||
bool[] status = await _modbusMaster?.ReadCoilsAsync(0x01, coil, 1);
|
||||
if (status != null && status[0] == val) { WriteLog(log); ShowSuccess(ok); }
|
||||
else ShowError(err);
|
||||
}
|
||||
catch (Exception ex) { ShowError(_lang == "en-US" ? $"Communication error: {ex.Message}" : $"通信错误: {ex.Message}"); }
|
||||
}
|
||||
|
||||
|
||||
@@ -922,31 +799,7 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
}
|
||||
|
||||
|
||||
//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)
|
||||
{
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
/// </summary>
|
||||
public partial class ParameterConfigWindow : Window
|
||||
{
|
||||
private readonly string _lang = ConfigurationManager.AppSettings["Language"] ?? "zh-CN";
|
||||
Function ma;
|
||||
DataChange c = new DataChange();
|
||||
#region 数据模型(存储参数值)
|
||||
@@ -97,9 +98,10 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
}
|
||||
|
||||
// 消息提示封装(统一风格)
|
||||
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 ShowSuccess(string message) => MessageBox.Show(message, _lang == "en-US" ? "Success" : "成功", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
private void ShowWarning(string message) => MessageBox.Show(message, _lang == "en-US" ? "Warning" : "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
private void ShowError(string message) => MessageBox.Show(message, _lang == "en-US" ? "Error" : "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -412,22 +414,22 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
private async void OnCalibrateExpiratoryClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await WriteCoilWithCheck(
|
||||
coilAddress: 71,
|
||||
value: true,
|
||||
successMsg: "校准指令已被设备接收并执行",
|
||||
failMsg: "校准执行超时,状态异常",
|
||||
logMsg: "校准指令执行成功");
|
||||
coilAddress: 71,
|
||||
value: true,
|
||||
successMsg: _lang == "en-US" ? "Calibration success" : "校准指令已被设备接收并执行",
|
||||
failMsg: _lang == "en-US" ? "Calibration timeout" : "校准执行超时,状态异常",
|
||||
logMsg: _lang == "en-US" ? "Calibration executed" : "校准指令执行成功");
|
||||
}
|
||||
|
||||
// 吸流量校准按钮
|
||||
private async void OnCalibrateInspiratoryClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await WriteCoilWithCheck(
|
||||
coilAddress: 104,
|
||||
value: true,
|
||||
successMsg: "校准指令已被设备接收并执行",
|
||||
failMsg: "校准执行超时,状态异常",
|
||||
logMsg: "校准指令执行成功");
|
||||
coilAddress: 104,
|
||||
value: true,
|
||||
successMsg: _lang == "en-US" ? "Calibration success" : "校准指令已被设备接收并执行",
|
||||
failMsg: _lang == "en-US" ? "Calibration timeout" : "校准执行超时,状态异常",
|
||||
logMsg: _lang == "en-US" ? "Calibration executed" : "校准指令执行成功");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -438,65 +440,50 @@ namespace ShanghaiEnvironmentalTechnology
|
||||
return _modbusMaster != null && _tcpClient?.Connected == true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入线圈并验证状态
|
||||
/// </summary>
|
||||
private async Task WriteCoilWithCheck(
|
||||
ushort coilAddress,
|
||||
bool value,
|
||||
string successMsg,
|
||||
string failMsg,
|
||||
string logMsg)
|
||||
ushort coilAddress,
|
||||
bool value,
|
||||
string successMsg,
|
||||
string failMsg,
|
||||
string logMsg)
|
||||
{
|
||||
if (!IsModbusConnected())
|
||||
{
|
||||
ShowError("Modbus TCP 未连接");
|
||||
ShowError(_lang == "en-US" ? "Modbus TCP not connected" : "Modbus TCP 未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 写入线圈
|
||||
await Task.Run(() =>
|
||||
_modbusMaster?.WriteSingleCoilAsync(0x01, coilAddress, value)
|
||||
);
|
||||
await Task.Run(() => _modbusMaster?.WriteSingleCoilAsync(0x01, coilAddress, value));
|
||||
Thread.Sleep(200);
|
||||
if (failMsg != null && (failMsg.Contains("停止") || failMsg.Contains("校准")))
|
||||
|
||||
if (failMsg != null && (failMsg.Contains("Stop") || failMsg.Contains("Calib") || failMsg.Contains("校准") || failMsg.Contains("停止")))
|
||||
{
|
||||
// 写入线圈
|
||||
await Task.Run(() =>
|
||||
_modbusMaster?.WriteSingleCoilAsync(0x01, coilAddress, false)
|
||||
);
|
||||
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 (failMsg != null && !failMsg.Contains("Stop") && !failMsg.Contains("Calib") && !failMsg.Contains("校准") && !failMsg.Contains("停止"))
|
||||
{
|
||||
if (status[0] == value)
|
||||
if (status != null && status.Length > 0 && status[0] == value)
|
||||
{
|
||||
// 写入日志
|
||||
WriteLog($"{logMsg} - 地址:{coilAddress},状态:{value}");
|
||||
if (!string.IsNullOrEmpty(successMsg))
|
||||
{
|
||||
ShowSuccess(successMsg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowError(failMsg);
|
||||
WriteLog($"{logMsg} - Address: {coilAddress}, State: {value}");
|
||||
if (!string.IsNullOrEmpty(successMsg)) ShowSuccess(successMsg);
|
||||
}
|
||||
else ShowError(failMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(successMsg)) ShowSuccess(successMsg);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowError($"通信错误: {ex.Message}");
|
||||
ShowError(_lang == "en-US" ? $"Communication error: {ex.Message}" : $"通信错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user