Files
huadongmocaceshiyi/MainWindow.xaml.cs

795 lines
31 KiB
C#
Raw Normal View History

2026-03-11 16:42:31 +08:00
using Modbus.Device;
using Sunny.UI;
using System;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using ;
namespace PLCDataMonitor
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
// 数据属性
private Brush _statusColor;
private string _connectionStatus;
string _plcIpAddress = string.Empty;
int _plcPort = 502;
private bool _isConnected;
private Thread _readThread;
private bool _keepReading;
private Function ma;
private DataChange c = new DataChange();
// 关键修改:创建一个共享的线程安全数据队列
private System.Collections.Concurrent.ConcurrentQueue<Tuple<DateTime, double, double>> _sharedCurveDataQueue = new System.Collections.Concurrent.ConcurrentQueue<Tuple<DateTime, double, double>>();
// 页面实例
private HomePage _homePage;
private ReportPage _reportPage;
private CurvePage _curvePage;
// 属性更改通知事件
public event PropertyChangedEventHandler PropertyChanged;
private TcpClient _tcpClient;
private IModbusMaster _modbusMaster;
2026-03-11 19:11:06 +08:00
2026-03-24 19:34:22 +08:00
// 暂停控制HR500.04
private const int PauseControlCoil = 41204; // 写入 true=暂停false=继续
private const int PauseStatusCoil = 41204; // 读取当前暂停状态(同一地址)
2026-03-11 19:11:06 +08:00
// 记录暂停时间段(用于导出过滤)
private List<(DateTime start, DateTime end)> _pausePeriods = new List<(DateTime, DateTime)>();
private bool _lastPausedState = false; // 上一次读取的暂停状态
private DateTime _pauseStartTime; // 本次暂停开始时间
public List<(DateTime start, DateTime end)> PausePeriods => _pausePeriods;
2026-03-25 21:19:50 +08:00
// 【新增】用于记录净运行时间的秒表
private System.Diagnostics.Stopwatch _testStopwatch = new System.Diagnostics.Stopwatch();
// 【新增】用于检测新一轮测试开始
private int _lastActualCount = 0;
private int _lastSetCount = 0;
2026-03-11 19:11:06 +08:00
// 添加清空方法
public void ClearPausePeriods()
{
_pausePeriods.Clear();
_lastPausedState = false;
_pauseStartTime = default;
}
2026-03-11 16:42:31 +08:00
// 连接状态属性
public Brush StatusColor
{
get { return _statusColor; }
set { _statusColor = value; OnPropertyChanged(nameof(StatusColor)); }
}
public string ConnectionStatus
{
get { return _connectionStatus; }
set { _connectionStatus = value; OnPropertyChanged(nameof(ConnectionStatus)); }
}
// 报表相关:记录是否已插入当前批次报表(避免重复插入)
public bool _hasInsertedReport = false;
public MainWindow()
{
InitializeComponent();
DataContext = this;
// 初始化状态
StatusColor = Brushes.Red;
ConnectionStatus = "未连接";
_homePage = new HomePage();
2026-03-11 19:11:06 +08:00
// 订阅暂停/继续事件
_homePage.PauseRequested += (s, e) => SendPauseCommand();
_homePage.ResumeRequested += (s, e) => SendResumeCommand();
2026-03-11 16:42:31 +08:00
// 关键修改:创建报表页时传入共享队列
_reportPage = new ReportPage();
_reportPage.CurveDataQueue = _sharedCurveDataQueue;
// 关键修改:创建曲线页时传入同一个共享队列
_curvePage = new CurvePage(_sharedCurveDataQueue);
// 默认显示数据监控页
MainContentFrame.Navigate(_homePage);
SetupLogging();
_reportPage.OnExportCompleted += () =>
{
_hasInsertedReport = false; // 重置插入标记
};
2026-03-25 19:45:13 +08:00
// 设置IP和端口显示
string ip = ConfigurationManager.AppSettings["PLC_IP"];
string port = ConfigurationManager.AppSettings["PLC_PORT"];
TxtPLCIPValue.Text = string.IsNullOrEmpty(ip) ? "192.168.1.170" : ip;
TxtPLCPortValue.Text = string.IsNullOrEmpty(port) ? "502" : port;
2026-03-11 16:42:31 +08:00
}
public void SetupLogging()
{
var logFilePath = "log.txt";
var fileListener = new TextWriterTraceListener(File.CreateText(logFilePath));
Trace.Listeners.Add(fileListener);
Trace.AutoFlush = true;
}
private void InitializeModbusTcp()
{
try
{
_tcpClient = new TcpClient();
_plcIpAddress = ConfigurationManager.AppSettings["PLC_IP"];
_plcPort = ConfigurationManager.AppSettings["PLC_PORT"].ToString().ToInt16();
var connectResult = _tcpClient.BeginConnect(_plcIpAddress, _plcPort, null, null);
var success = connectResult.AsyncWaitHandle.WaitOne(3000);
if (!success || !_tcpClient.Connected)
throw new Exception("连接PLC超时请检查IP和端口");
_modbusMaster = ModbusIpMaster.CreateIp(_tcpClient);
_modbusMaster.Transport.ReadTimeout = 1000;
_modbusMaster.Transport.WriteTimeout = 1000;
ma = new Function(_modbusMaster);
}
catch (Exception ex)
{
throw new Exception($"Modbus初始化失败{ex.Message}");
}
}
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void BtnHome_Click(object sender, RoutedEventArgs e)
{
UpdateNavButtonStyle(BtnHome, BtnReport, BtnCurve);
MainContentFrame.Navigate(_homePage);
}
private void BtnReport_Click(object sender, RoutedEventArgs e)
{
UpdateNavButtonStyle(BtnReport, BtnHome, BtnCurve);
MainContentFrame.Navigate(_reportPage);
}
private void BtnCurve_Click(object sender, RoutedEventArgs e)
{
UpdateNavButtonStyle(BtnCurve, BtnHome, BtnReport);
MainContentFrame.Navigate(_curvePage);
}
private void UpdateNavButtonStyle(FrameworkElement activeBtn,
params FrameworkElement[] inactiveBtns)
{
if (activeBtn is Button btnActive)
{
btnActive.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#3498DB"));
}
foreach (var btn in inactiveBtns)
{
if (btn is Button btnInactive)
{
btnInactive.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#2C3E50"));
}
}
}
private void ConnectToPLC()
{
try
{
Trace.WriteLine("Initializing Modbus TCP connection...");
InitializeModbusTcp();
_isConnected = true;
StatusColor = Brushes.Green;
ConnectionStatus = "已连接";
Trace.WriteLine("Connection established successfully.");
StartReadingData();
}
catch (Exception ex)
{
Trace.WriteLine($"Connection failed: {ex.Message}");
Trace.WriteLine($"Stack Trace: {ex.StackTrace}");
MessageBox.Show($"连接失败:{ex.Message}", "错误",
MessageBoxButton.OK, MessageBoxImage.Error);
StatusColor = Brushes.Orange;
ConnectionStatus = "连接失败";
}
}
private void DisconnectFromPLC()
{
try
{
_keepReading = false;
2026-03-25 19:45:13 +08:00
// 等待线程结束,最多 2 秒
2026-03-11 16:42:31 +08:00
if (_readThread != null && _readThread.IsAlive)
{
2026-03-25 19:45:13 +08:00
if (!_readThread.Join(2000))
2026-03-11 16:42:31 +08:00
{
2026-03-25 19:45:13 +08:00
// 如果线程未结束,强制终止(慎用)
// _readThread.Abort(); // 不推荐,此处仅为保底
2026-03-11 16:42:31 +08:00
}
}
_modbusMaster?.Dispose();
_modbusMaster = null;
if (_tcpClient != null)
{
2026-03-25 19:45:13 +08:00
if (_tcpClient.Connected)
_tcpClient.Close();
2026-03-11 16:42:31 +08:00
_tcpClient.Dispose();
_tcpClient = null;
}
_isConnected = false;
StatusColor = Brushes.Red;
ConnectionStatus = "已断开";
_homePage.UpdateData("0.0", "0.0", "0.0", "0.0", 0, 0, "0", "0", "0");
}
catch (Exception ex)
{
MessageBox.Show($"断开失败:{ex.Message}", "错误",
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void StartReadingData()
{
_keepReading = true;
_readThread = new Thread(ReadDataLoop) { IsBackground = true };
_readThread.Start();
}
private void ReadDataLoop()
{
2026-03-11 19:11:16 +08:00
//int i = 0;
//while (i < 100)
//{
// // 添加随机测试数据
// Random random = new Random();
// // 生成随机摩擦力值(包含负值)
// double friction1 = random.Next(-200, 200);
// double friction2 = random.Next(-200, 200);
// // 创建数据点(时间戳相同,确保数据一致性)
// var dataPoint = new Tuple<DateTime, double, double>(
// DateTime.Now,
// friction1,
// friction2
// );
// // 关键修改:同时添加到两个地方
// // 1. 添加到共享曲线数据队列(曲线页面和报表页面共享)
// _sharedCurveDataQueue.Enqueue(dataPoint);
// // 2. 添加到报表数据
// _reportPage.AddReportRecord(new ReportData
// {
// D = random.Next(1, 100),
// Friction1 = friction1.ToString("F1"), // 使用相同的摩擦力值
// Friction2 = friction2.ToString("F1"), // 使用相同的摩擦力值
// Id = (i + 11).ToString(),
// Pressure1 = random.Next(1, 10).ToString(),
// Pressure2 = random.Next(2, 12).ToString(),
// t1 = random.Next(20, 40),
// t2 = random.Next(25, 45),
// Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") // 使用相同的时间格式
// });
// // 3. 通知曲线页面更新(这个调用只是触发重绘,数据已经在队列中)
// _curvePage.AddFrictionData(friction1, friction2);
// // 为了让曲线更平滑,可以少量数据生成
// Thread.Sleep(100); // 每100ms一个数据点
// i++;
//}
2026-03-11 16:42:31 +08:00
while (_keepReading)
{
try
{
if (_isConnected && _tcpClient != null && _tcpClient.Connected)
{
// 读取所有数据(包含新增的次数、最大摩擦力)
var data = ReadModbusData();
2026-03-11 19:11:06 +08:00
// 读取暂停状态
bool isPaused = false;
try
{
bool[] pauseStatus = _modbusMaster?.ReadCoils(0x01, (ushort)PauseStatusCoil, 1);
isPaused = pauseStatus != null && pauseStatus.Length > 0 && pauseStatus[0];
}
catch
{
// 读取失败时默认 false
}
// --- 记录暂停时间段 ---
if (isPaused != _lastPausedState)
{
if (isPaused) // 进入暂停
{
_pauseStartTime = DateTime.Now;
}
else // 退出暂停
{
if (_pauseStartTime != default)
{
_pausePeriods.Add((_pauseStartTime, DateTime.Now));
}
}
_lastPausedState = isPaused;
2026-03-24 19:34:22 +08:00
// 【新增】同步更新 HomePage 上的按钮状态
Dispatcher.BeginInvoke(new Action(() =>
{
_homePage.SetButtonState(isPaused);
}), System.Windows.Threading.DispatcherPriority.Background);
2026-03-11 19:11:06 +08:00
}
2026-03-25 21:19:50 +08:00
// 【核心修改】1. 控制秒表逻辑 (处理暂停和重新开始)
// 判断是否是新的一轮测试开始 (实际次数归1或者从上一轮结束状态变为1)
bool isNewTestStart = (data.actualCount == 1 && _lastActualCount == 0) ||
(data.actualCount == 1 && _lastActualCount == _lastSetCount && _lastSetCount > 0);
if (isNewTestStart)
{
// 新一轮测试,重置并启动秒表
_testStopwatch.Restart();
}
else
{
// 非新一轮,根据暂停状态控制秒表
if (!isPaused && data.setCount > 0 && data.actualCount > 0)
{
// 测试进行中且未暂停 -> 启动秒表 (如果之前是停的)
if (!_testStopwatch.IsRunning) _testStopwatch.Start();
}
else
{
// 暂停中 或 测试未开始 -> 停止秒表
if (_testStopwatch.IsRunning) _testStopwatch.Stop();
}
}
// 更新记录,供下一次循环判断
_lastActualCount = data.actualCount;
_lastSetCount = data.setCount;
// 【核心修改】2. 生成“净运行时间”戳
// 使用 DateTime.MinValue 作为基准,加上秒表时间。
// 这样计算 TotalSeconds 时,得到的就是纯粹的秒数,不包含暂停时间。
DateTime effectiveTime = DateTime.MinValue.AddMilliseconds(_testStopwatch.ElapsedMilliseconds);
2026-03-11 19:11:06 +08:00
// --- 结束记录暂停时间段 ---
2026-03-11 16:42:31 +08:00
var pressure1 = data.pressure1;
var pressure2 = data.pressure2;
var friction1 = data.friction1;
var friction2 = data.friction2;
var maxFriction1 = data.maxFriction1;
var maxFriction2 = data.maxFriction2;
2026-03-21 11:15:47 +08:00
2026-03-24 19:34:22 +08:00
// ----- 读取报警状态HR504 / HR509-----
bool[] alarmsHR504 = null;
bool[] alarmsHR509 = null;
2026-03-21 11:15:47 +08:00
try
{
2026-03-24 19:34:22 +08:00
// 连续读取 HR504.1 ~ HR504.55个线圈起始 41265
alarmsHR504 = _modbusMaster?.ReadCoils(0x01, 41265, 5);
// 连续读取 HR509.0 ~ HR509.34个线圈起始 41345
2026-03-25 19:45:13 +08:00
alarmsHR509 = _modbusMaster?.ReadCoils(0x01, 41344, 6);
}
catch
{
2026-03-21 11:15:47 +08:00
}
string alarmMessage = "";
2026-03-24 19:34:22 +08:00
if (alarmsHR504 != null && alarmsHR504.Length >= 5)
2026-03-21 11:15:47 +08:00
{
2026-03-24 19:34:22 +08:00
// 根据实测索引0=41265=已达上限水位
if (alarmsHR504[0]) alarmMessage += "已达上限水位 ";
// 索引1=41266=急停被按下
if (alarmsHR504[1]) alarmMessage += "急停被按下 ";
// 索引2=41267=测试完成(待确认)
if (alarmsHR504[2]) alarmMessage += "测试完成 ";
// 索引3=41268=摩擦力过大(待确认)
2026-03-25 19:45:13 +08:00
//if (alarmsHR504[3]) alarmMessage += "摩擦力过大 ";
2026-03-24 19:34:22 +08:00
// 索引4=41269=超温95℃待确认
if (alarmsHR504[4]) alarmMessage += "超温95℃ ";
2026-03-21 11:15:47 +08:00
}
2026-03-25 19:45:13 +08:00
if (alarmsHR509 != null && alarmsHR509.Length >= 6)
2026-03-21 11:15:47 +08:00
{
2026-03-24 19:34:22 +08:00
if (alarmsHR509[0]) alarmMessage += "1工位低水位 ";
if (alarmsHR509[2]) alarmMessage += "水泵未运行 ";
// 索引3=41348=2工位低水位
if (alarmsHR509[3]) alarmMessage += "2工位低水位 ";
2026-03-25 19:45:13 +08:00
if (alarmsHR509[4]) alarmMessage += "摩擦力过大 ";
if (alarmsHR509[5]) alarmMessage += "伺服驱动器报警,请清除 ";
2026-03-21 11:15:47 +08:00
}
2026-03-25 19:45:13 +08:00
2026-03-21 11:15:47 +08:00
2026-03-11 16:42:31 +08:00
// 更新UI数据监控页+曲线页)
// 使用 BeginInvoke 避免阻塞后台读取线程,减少 UI 卡死风险
Dispatcher.BeginInvoke(new Action(() =>
{
// 更新数据监控页数值
_homePage.UpdateData(
pressure1.ToString("F1"),
pressure2.ToString("F1"),
friction1.ToString("F1"),
friction2.ToString("F1"),
data.setCount,
data.actualCount,
data.t1.ToString("F1"),
data.t2.ToString("F1"),
data.D.ToString("F1")
);
2026-03-21 11:15:47 +08:00
// 新增:更新报警显示
_homePage.UpdateAlarms(alarmMessage);
2026-03-24 19:34:22 +08:00
if (!isPaused)
2026-03-11 16:42:31 +08:00
{
2026-03-24 19:34:22 +08:00
// 关键修改:确保曲线数据正确记录
if (data.setCount > 0 && data.actualCount > 0 &&
data.setCount > data.actualCount) // 点击了开始,且实际次数小于设定次数,才更新曲线
{
// 创建数据点
var dataPoint = new Tuple<DateTime, double, double>(
2026-03-26 10:50:18 +08:00
effectiveTime,
2026-03-24 19:34:22 +08:00
friction1,
friction2
);
2026-03-11 16:42:31 +08:00
2026-03-24 19:34:22 +08:00
// 添加到共享队列
_sharedCurveDataQueue.Enqueue(dataPoint);
2026-03-11 16:42:31 +08:00
2026-03-24 19:34:22 +08:00
// 通知曲线页面更新
_curvePage.AddFrictionData(friction1, friction2);
2026-03-11 16:42:31 +08:00
2026-03-24 19:34:22 +08:00
}
2026-03-11 16:42:31 +08:00
2026-03-24 19:34:22 +08:00
if (data.setCount > 0 && data.actualCount > 0 &&
data.setCount == data.actualCount && !_hasInsertedReport) // 一次测试执行完成,保存报表
{
2026-03-25 21:19:50 +08:00
//// 创建报表记录(时间+压力+最大摩擦力)
//var reportRecord = new ReportData(
// DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), // 当前时间
// pressure1.ToString("F1"), // 工位1压力
// pressure2.ToString("F1"), // 工位2压力
// maxFriction1.ToString("F1"), // 工位1最大摩擦力
// maxFriction2.ToString("F1"),
// data.t1,
// data.t2,
// data.D
//);
// 获取当前的净运行秒数
double currentElapsedSec = _testStopwatch.ElapsedMilliseconds / 1000.0;
2026-03-24 19:34:22 +08:00
var reportRecord = new ReportData(
2026-03-25 21:19:50 +08:00
currentElapsedSec.ToString(), // 绝对时间可以保留作为“发生时刻”,或者改为显示秒数
pressure1.ToString("F1"),
pressure2.ToString("F1"),
maxFriction1.ToString("F1"),
2026-03-24 19:34:22 +08:00
maxFriction2.ToString("F1"),
data.t1,
data.t2,
data.D
2026-03-25 21:19:50 +08:00
// 注意:如果你的 ReportData 构造函数没有 ElapsedSeconds 参数,需要重载构造函数或直接赋值
2026-03-24 19:34:22 +08:00
);
2026-03-25 21:19:50 +08:00
reportRecord.ElapsedSeconds = currentElapsedSec;
2026-03-24 19:34:22 +08:00
// 插入报表
_reportPage.AddReportRecord(reportRecord);
// 标记为已插入(避免同一批次重复插入)
_hasInsertedReport = true;
}
if (data.actualCount < data.setCount)
{
_hasInsertedReport = false;
}
2026-03-11 16:42:31 +08:00
}
2026-03-24 19:34:22 +08:00
2026-03-11 16:42:31 +08:00
}), System.Windows.Threading.DispatcherPriority.Background);
}
2026-03-25 19:45:13 +08:00
else
{
// 如果连接标志为 true 但实际未连接,主动断开
if (_isConnected)
{
Dispatcher.BeginInvoke(new Action(() => DisconnectFromPLC()));
}
}
2026-03-11 16:42:31 +08:00
}
catch (Exception ex)
{
2026-03-25 19:45:13 +08:00
// 捕获 Socket 异常
if (ex is SocketException || (ex.InnerException is SocketException) ||
ex.Message.Contains("non-connected") || ex.Message.Contains("socket"))
2026-03-11 16:42:31 +08:00
{
2026-03-25 19:45:13 +08:00
// 连接已丢失,触发断开
Dispatcher.BeginInvoke(new Action(() => DisconnectFromPLC()));
}
else
{
// 其他异常正常显示
Dispatcher.BeginInvoke(new Action(() =>
{
StatusColor = Brushes.Orange;
ConnectionStatus = $"读取错误:{ex.Message}";
}), System.Windows.Threading.DispatcherPriority.Background);
}
2026-03-11 16:42:31 +08:00
}
Thread.Sleep(200); // 100ms刷新一次
}
}
2026-03-25 21:19:50 +08:00
public void ResetTestTimer()
{
if (_testStopwatch != null)
{
_testStopwatch.Reset();
}
// 同时也重置一下计数记录,防止逻辑判断错误
_lastActualCount = 0;
_lastSetCount = 0;
}
2026-03-11 16:42:31 +08:00
private (float pressure1, float pressure2, float friction1, float friction2,
int setCount, int actualCount, float maxFriction1, float maxFriction2, float t1, float t2, float D, bool status) ReadModbusData()
{
try
{
// 修正地址按手册公式计算后的Modbus地址
ushort[] p1 = _modbusMaster?.ReadHoldingRegisters(0x01, 18701, 2); // 原DM170017001+1700=18701
ushort[] p2 = _modbusMaster?.ReadHoldingRegisters(0x01, 18705, 2); // 原DM170417001+1704=18705
ushort[] f1 = _modbusMaster?.ReadHoldingRegisters(0x01, 17045, 2); // 原DM4417001+44=17045
ushort[] f2 = _modbusMaster?.ReadHoldingRegisters(0x01, 17085, 2); // 原DM8417001+84=17085
// 设定次数H64
ushort[] setCountArr = _modbusMaster?.ReadHoldingRegisters(0x01, 6734, 1);
ushort[] actualCountArr = _modbusMaster?.ReadHoldingRegisters(0x01, 19000, 1);
// 最大摩擦力1DM160017001+1600=18601
ushort[] maxF1Arr = _modbusMaster?.ReadHoldingRegisters(0x01, 18601, 2);
// 最大摩擦力2DM160417001+1604=18605
ushort[] maxF2Arr = _modbusMaster?.ReadHoldingRegisters(0x01, 18605, 2);
// 温度和其他数据
ushort[] p11 = _modbusMaster?.ReadHoldingRegisters(0x01, 18201, 2);
ushort[] p12 = _modbusMaster?.ReadHoldingRegisters(0x01, 18205, 2);
ushort[] p13 = _modbusMaster?.ReadHoldingRegisters(0x01, 19101, 2);
bool[] p14 = _modbusMaster?.ReadCoils(0x01, 7100, 100);
if (p14[0])
{
}
// 转换数据压力、实时摩擦力float类型
float pressure1 = c.UshortToFloat(p1[0], p1[1]);
float pressure2 = c.UshortToFloat(p2[0], p2[1]);
float friction1 = c.UshortToFloat(f1[0], f1[1]);
float friction2 = c.UshortToFloat(f2[0], f2[1]);
float pressure11 = c.UshortToFloat(p11[0], p11[1]);
float pressure12 = c.UshortToFloat(p12[0], p12[1]);
float pressure13 = c.UshortToFloat(p13[0], p13[1]);
// 转换数据设定次数、实际次数int类型
int setCount = setCountArr[0]; // 16位寄存器直接转int
int actualCount = actualCountArr[0];
// 转换数据最大摩擦力float类型
float maxFriction1 = c.UshortToFloat(maxF1Arr[0], maxF1Arr[1]);
float maxFriction2 = c.UshortToFloat(maxF2Arr[0], maxF2Arr[1]);
bool stauts = p14[0];
// 保留4位小数返回
return (
(float)Math.Round(pressure1, 4),
(float)Math.Round(pressure2, 4),
(float)Math.Round(friction1, 4),
(float)Math.Round(friction2, 4),
setCount,
actualCount,
maxFriction1,
maxFriction2,
pressure11,
pressure12,
pressure13,
stauts
);
}
catch (Exception ex)
{
2026-03-25 19:45:13 +08:00
//throw new Exception($"Modbus读取错误{ex.Message}");
return (
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
true
);
2026-03-11 16:42:31 +08:00
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
DisconnectFromPLC();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
2026-03-25 19:45:13 +08:00
//if (!_isConnected)
//{
// ConnectToPLC();
// if (_isConnected)
// {
// BtnConnectPLC.Content = "断开PLC";
// BtnConnectPLC.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#E67E22"));
// }
//}
//else
//{
// DisconnectFromPLC();
// BtnConnectPLC.Content = "连接PLC";
// BtnConnectPLC.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#27AE60"));
//}
// 只做界面初始化,不自动连接
// 确保连接按钮状态正确
BtnConnectPLC.Content = "连接PLC";
BtnConnectPLC.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#27AE60"));
StatusColor = Brushes.Red;
ConnectionStatus = "未连接";
2026-03-11 16:42:31 +08:00
}
private void ConnectButton_Click(object sender, RoutedEventArgs e)
{
if (!_isConnected)
{
ConnectToPLC();
2026-03-25 19:45:13 +08:00
// 更新按钮文本
BtnConnectPLC.Content = "断开PLC";
BtnConnectPLC.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#E67E22"));
2026-03-11 16:42:31 +08:00
}
else
{
DisconnectFromPLC();
2026-03-25 19:45:13 +08:00
BtnConnectPLC.Content = "连接PLC";
BtnConnectPLC.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#27AE60"));
2026-03-11 16:42:31 +08:00
}
}
2026-03-11 19:11:06 +08:00
private void SendPauseCommand()
{
try
{
if (_isConnected && _modbusMaster != null)
{
_modbusMaster.WriteSingleCoil(0x01, (ushort)PauseControlCoil, true);
2026-03-24 19:34:22 +08:00
Thread.Sleep(100);
2026-03-11 19:11:06 +08:00
}
}
catch (Exception ex)
{
MessageBox.Show($"发送暂停命令失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void SendResumeCommand()
{
try
{
if (_isConnected && _modbusMaster != null)
{
_modbusMaster.WriteSingleCoil(0x01, (ushort)PauseControlCoil, false);
2026-03-24 19:34:22 +08:00
Thread.Sleep(100);
2026-03-11 19:11:06 +08:00
}
}
catch (Exception ex)
{
MessageBox.Show($"发送继续命令失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
2026-03-11 16:42:31 +08:00
}
}