Files
hoodFieldOfView/头罩视野slove/头罩视野/Views/RecordDate.xaml.cs
2026-04-22 14:45:50 +08:00

216 lines
7.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using 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
{
/// <summary>
/// RecordDate.xaml 的交互逻辑
/// </summary>
///
public partial class RecordDate : Page
{
private IModbusMaster _modbusMaster => ModbusResourceManager.Instance.ModbusMaster;
private System.Timers.Timer _plcReadTimer;
// 表跟数据存储列表
private List<dynamic> LeftEyeDataList = new List<dynamic>();
private List<dynamic> RightEyeDataList = new List<dynamic>();
// 配置和你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<dynamic> dataList, DataGrid dg)
{
dynamic row = new System.Dynamic.ExpandoObject();
var dict = (IDictionary<string, object>)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()); 页面相互跳转
}
}