页面逻辑添加

This commit is contained in:
2026-04-24 14:55:20 +08:00
parent dade596792
commit e59fed9b91
3 changed files with 383 additions and 58 deletions

View File

@@ -16,6 +16,7 @@ using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using .Services.Data;
using static .TestDataStore;
namespace .Views
{
/// <summary>
@@ -32,11 +33,16 @@ namespace 头罩视野.Views
private List<dynamic> LeftEyeDataList = new List<dynamic>();
private List<dynamic> RightEyeDataList = new List<dynamic>();
// 配置和你PLC地址完全对应
// 配置和你PLC地址完全对应 左目
private const int LeftEyeStartAddress = 1362; // D1362
private const int ChannelCount = 72; // 72个通道
private const int RegistersPerChannel = 2; // 每个通道2个寄存器Float
//右目
private const int RightEyeStartAddress = 1218; // D1218
// 长按清除用
private bool _isClearPressed = false;
private Thread _clearThread;
@@ -83,64 +89,158 @@ namespace 头罩视野.Views
}
private void ReadPlcData(object? sender, ElapsedEventArgs e)
{
// 左通道
ReadPlcDataGeneric(
slaveAddress: 1,
startAddress: LeftEyeStartAddress,
count: (ushort)(ChannelCount * RegistersPerChannel),
dataList: LeftEyeDataList,
dataGrid: dataGrid1);
// 右通道
ReadPlcDataGeneric(
slaveAddress: 1,
startAddress: RightEyeStartAddress,
count: (ushort)(ChannelCount * RegistersPerChannel),
dataList: RightEyeDataList,
dataGrid: dataGrid2);
}
private void ReadPlcDataGeneric(int slaveAddress, int startAddress, ushort count, List<dynamic> dataList, DataGrid dataGrid)
{
throw new NotImplementedException();
}
/// <summary>
/// 读取PLC HoldingRegisters 并更新到列表和DataGrid
/// <param name="slaveAddress">设备站号一般是1</param>
/// <param name="startAddress">起始地址</param>
/// <param name="count">寄存器总数</param>
/// <param name="dataList">数据缓存列表</param>
/// <param name="dataGrid">要更新的DataGrid控件</param>
/// 通用PLC读取方法左右通道通用
/// </summary>
private void ReadPlcDataGeneric(
byte slaveAddress,
ushort startAddress,
ushort count,
List<ushort> dataList,
DataGrid dataGrid)
{
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
);
slaveAddress: slaveAddress,
startAddress: startAddress,
numberOfPoints: count);
// 把寄存器转换成浮点数,并添加到表格
// 先把变量存为局部变量,解决闭包问题
var regCopy = registers;
var listCopy = dataList;
var gridCopy = dataGrid;
// 交给UI线程更新数据和表格
Dispatcher.Invoke(() =>
{
AddPlcDataRow(registers, LeftEyeDataList, dataGrid1);
AddPlcDataRow(regCopy, listCopy, gridCopy);
});
}
catch (Exception ex)
{
// 读取失败不报错,避免程序崩溃
Console.WriteLine($"PLC读取错误{ex.Message}");
Console.WriteLine($"PLC读取失败: {ex.Message}");
}
}
//把 PLC 数据添加到你的动态表格
private void AddPlcDataRow(ushort[] registers, List<dynamic> dataList, DataGrid dg)
/// <summary>
/// 把PLC数据添加到动态表格
/// </summary>
private void AddPlcDataRow(ushort[] registers, List<ushort> dataList, DataGrid dg)
{
dynamic row = new System.Dynamic.ExpandoObject();
var dict = (IDictionary<string, object>)row;
// 清空旧数据,防止重复
dataList.Clear();
// 固定列:编号、时间、日期
dict["Id"] = dataList.Count + 1;
dict["Time"] = DateTime.Now.ToString("HH:mm:ss");
dict["Date"] = DateTime.Now.ToString("yyyy-MM-dd");
// 把PLC数据存入列表
dataList.AddRange(registers);
// 通道列把寄存器转成Float
for (int i = 0; i < ChannelCount; i++)
// 构建动态行适配你原来的ExpandoObject逻辑
List<dynamic> rows = new List<dynamic>();
for (int i = 0; i < registers.Length; i++)
{
// 每个Float占2个寄存器
ushort high = registers[i * 2];
ushort low = registers[i * 2 + 1];
dynamic row = new System.Dynamic.ExpandoObject();
var dict = (IDictionary<string, object>)row;
// 组合成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["Id"] = i + 1;
dict["Time"] = DateTime.Now.ToString("HH:mm:ss");
dict["Value"] = registers[i];
dict[$"Ch{i + 1}"] = Math.Round(value, 2); // 保留2位小数
rows.Add(row);
}
// 加到列表和表格
dataList.Add(row);
dg.Items.Add(row);
// 更新DataGrid
dg.ItemsSource = null;
dg.ItemsSource = rows;
//根据不的dg 值 可以算出 左/右目视野面积
}
//private void AddPlcDataRow()
//{
// AddPlcDataRow(LeftEyeDataList);
//}
//左右目面积调用方法
private void AddPlcDataRow(List<dynamic> leftEyeDataList, List<dynamic> RightEyeDataList)
{ //左目视野面积
GlobalData.LeftEyeArea = ModbusHelper.CalculateEyeArea(leftEyeDataList,
80,
120
);
//右目视野面积
GlobalData.RightEyeArea = ModbusHelper.CalculateEyeArea(RightEyeDataList,
80,
120
);
//双目视野面积
GlobalData.BinocularArea = ModbusHelper.CalcBinocularArea(leftEyeDataList, RightEyeDataList, 80, 120);
//// 总视野面积
GlobalData.TotalEyeArea = GlobalData.LeftEyeArea + GlobalData.RightEyeArea - GlobalData.BinocularArea;
//// 空白视野面积
GlobalData.BlankArea = 120 - GlobalData.TotalEyeArea;
//视野保存率
// 左眼平均值数组
double[] leftAvg = ModbusHelper.GetEyeAvgArray(leftEyeDataList);
// 右眼平均值数组
double[] rightAvg = ModbusHelper.GetEyeAvgArray(RightEyeDataList);
double leftLowerAngle = ModbusHelper.CalcLowerAngle(leftAvg, 10);
double rightLowerAngle = ModbusHelper.CalcLowerAngle(rightAvg, 10);
GlobalData.LowerVision = Math.Min(leftLowerAngle, rightLowerAngle);
//视野保存率
GlobalData.VisionRetentionRate = ModbusHelper.CalcVisionRate(GlobalData.LeftEyeArea, GlobalData.RightEyeArea);
}
private double CalcLowerAngle(double[] leftAvg, int v)
{
throw new NotImplementedException();
}
@@ -201,7 +301,7 @@ namespace 头罩视野.Views
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
}
@@ -212,4 +312,50 @@ namespace 头罩视野.Views
//NavigationService.Navigate(new Views.RecordDate()); 页面相互跳转
}
}
//// 公开定时器(让别的页面能访问)
//public System.Timers.Timer PlcReadTimer;
// // 公开:启动定时器
// public void StartRecordTimer()
// {
// if (PlcReadTimer == null)
// {
// PlcReadTimer = new System.Timers.Timer(100);
// PlcReadTimer.Elapsed += ReadPlcData; // 你的PLC读取方法
// PlcReadTimer.Start();
// }
// }
// // 公开:停止定时器
// public void StopRecordTimer()
// {
// if (PlcReadTimer != null)
// {
// PlcReadTimer.Stop();
// PlcReadTimer.Dispose();
// PlcReadTimer = null;
// }
// }
// // 你的PLC读取方法
// private void ReadPlcData(object sender, System.Timers.ElapsedEventArgs e)
// {
// // 你原来的逻辑
// }
// 找到 RecordDate 页面实例 页面调用和停止
//var recordPage = Application.Current.MainWindow
// .FindName("MainFrame") as Frame
// ?.Content as RecordDate;
//// 找到了就调用
//if (recordPage != null)
//{
// recordPage.StartRecordTimer(); // 启动
// // recordPage.StopRecordTimer(); // 停止
//}
}