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()); 页面相互跳转
}
}