using Microsoft.Win32; using Modbus.Device; using Sunny.UI; using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Timers; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using 头罩视野.Services.Data; namespace 头罩视野.Views { /// /// RecordDate.xaml 的交互逻辑 /// /// public partial class RecordDate : Page { private IModbusMaster _modbusMaster => ModbusResourceManager.Instance.ModbusMaster; private System.Timers.Timer _plcReadTimer; // 表跟数据存储列表 private List LeftEyeDataList = new List(); private List RightEyeDataList = new List(); // 配置:和你PLC地址完全对应 private const int LeftEyeStartAddress = 1362; // D1362 private const int ChannelCount = 72; // 72个通道 private const int RegistersPerChannel = 2; // 每个通道2个寄存器(Float) // 长按清除用 private bool _isClearPressed = false; private Thread _clearThread; public RecordDate() { InitializeComponent(); DynamicHeader(); // 2. 调用(名字和上面的变量一致) // 2. 启动定时器,定时读取数据(每100ms读一次) StartPlcReadTimer(100); //// 判断连接 if (!ModbusHelper.IsConnected) { MessageBox.Show("未连接"); return; } } //动态生成表头 void DynamicHeader() { // 2. 循环生成 64 个 ch 列 for (int i = 1; i <= ChannelCount; i++) { dataGrid1.Columns.Add(new DataGridTextColumn { Header = $"ch.{i}", Binding = new System.Windows.Data.Binding($"Ch{i}") }); dataGrid2.Columns.Add(new DataGridTextColumn { Header = $"ch.{i}", Binding = new System.Windows.Data.Binding($"Ch{i}") }); } } //定时读取 PLC 数据 private void StartPlcReadTimer(int intervalMs) { _plcReadTimer = new System.Timers.Timer(intervalMs); _plcReadTimer.Elapsed += ReadPlcData; _plcReadTimer.Start(); } private void ReadPlcData(object? sender, ElapsedEventArgs e) { if (_modbusMaster == null || !ModbusHelper.TcpClient.Connected) return; try { // 读取D1362开始的128个寄存器(64个通道×2) 参数定义:PLC 设备号默认1,数据起始地址D1362 要读的寄存器总数 ushort[] registers = _modbusMaster.ReadHoldingRegisters( slaveAddress: 1, // 从站地址,默认1 startAddress: LeftEyeStartAddress, numberOfPoints: ChannelCount * RegistersPerChannel ); // 把寄存器转换成浮点数,并添加到表格 Dispatcher.Invoke(() => { AddPlcDataRow(registers, LeftEyeDataList, dataGrid1); }); } catch (Exception ex) { // 读取失败不报错,避免程序崩溃 Console.WriteLine($"PLC读取错误:{ex.Message}"); } } //把 PLC 数据添加到你的动态表格 private void AddPlcDataRow(ushort[] registers, List dataList, DataGrid dg) { dynamic row = new System.Dynamic.ExpandoObject(); var dict = (IDictionary)row; // 固定列:编号、时间、日期 dict["Id"] = dataList.Count + 1; dict["Time"] = DateTime.Now.ToString("HH:mm:ss"); dict["Date"] = DateTime.Now.ToString("yyyy-MM-dd"); // 通道列:把寄存器转成Float for (int i = 0; i < ChannelCount; i++) { // 每个Float占2个寄存器 ushort high = registers[i * 2]; ushort low = registers[i * 2 + 1]; // 组合成32位浮点数 byte[] bytes = new byte[4]; bytes[0] = (byte)(low & 0xFF); bytes[1] = (byte)(low >> 8); bytes[2] = (byte)(high & 0xFF); bytes[3] = (byte)(high >> 8); float value = BitConverter.ToSingle(bytes, 0); dict[$"Ch{i + 1}"] = Math.Round(value, 2); // 保留2位小数 } // 加到列表和表格 dataList.Add(row); dg.Items.Add(row); } //#endregion // 保存左眼 private void btnSaveLeft_Click(object sender, RoutedEventArgs e) { //SaveToCsv(LeftEyeDataList, $"左眼数据_{DateTime.Now:yyyyMMddHHmmss}.csv"); ModbusHelper.SaveToCsv(LeftEyeDataList, $"左眼数据_{DateTime.Now:yyyyMMddHHmmss}.csv"); } // 保存右眼 private void btnSaveRight_Click(object sender, RoutedEventArgs e) { ModbusHelper.SaveToCsv(RightEyeDataList,$"右眼数据_{DateTime.Now:yyyyMMddHHmmss}.csv"); } //清除 private void btnClear_MouseDown(object sender, MouseButtonEventArgs e) { _isClearPressed = true; _clearThread = new Thread(() => { Thread.Sleep(500); // 长按1秒触发 if (_isClearPressed) { Application.Current.Dispatcher.Invoke(() => ClearAllData()); } }); _clearThread.Start(); } // 清除所有数据 private void ClearAllData() { LeftEyeDataList.Clear(); dataGrid1.Items.Clear(); RightEyeDataList.Clear(); dataGrid2.Items.Clear(); MessageBox.Show("数据已清除"); } private void btnClear_MouseUp(object sender, MouseButtonEventArgs e) { _isClearPressed = false; _clearThread?.Join(100); // 等待线程结束最多100毫秒,然后强制结束 } private void Page_Unloaded(object sender, RoutedEventArgs e) { _plcReadTimer?.Stop(); _plcReadTimer?.Dispose(); _modbusMaster?.Dispose(); ModbusHelper.TcpClient?.Close(); } private void Page_Loaded(object sender, RoutedEventArgs e) { } private void GoHome(object s, RoutedEventArgs e) => NavigationService.Content = null; private void GoTest(object s, RoutedEventArgs e) => NavigationService.Content = new Views.PageTest(); private void GoRecord(object s, RoutedEventArgs e) => NavigationService.Content = new Views.RecordDate(); private void GoView(object s, RoutedEventArgs e) => NavigationService.Content = new Views.RecordPage(); //NavigationService.Navigate(new Views.RecordDate()); 页面相互跳转 } }