增加工位号兼容功能 不依赖固定的 OP10 OP20做硬编码判定 通过App.config作为工位依据

This commit is contained in:
XingCheng3
2026-05-13 01:01:09 +08:00
parent 0ca8274260
commit 69b69af17f
6 changed files with 244 additions and 191 deletions

View File

@@ -1,44 +1,44 @@
using DC_A95;
using ExternalDataSync;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using SystemFramework;
using WebApi;
namespace MesWork
{
/// <summary>
/// 程式启动
/// </summary>
public partial class MesWorkForm
{
/// <summary>
/// 从这里启动
/// </summary>
/// <param name="e"></param>
protected override void OnShown(EventArgs e)
{
}
public void OnStart(params object[] o)
{
//【1】系统基本参数设定
ThreadPool.SetMaxThreads(workerThreads, completionPortThreads);
Never_Know.Hello_You_All_Never_Know = Hello_You_All_Never_Know;
// 加载信号表(按设备类型对应表展开多工位)
var (dt_Tag_Mes, dt_Device) = BuildSignalTable(BasicDataTableFile);
// 保存工位名称列表及显示名映射供UC_Weighing标题使用
StationOpNames = new System.Collections.Generic.List<string>();
StationDisplayNames = new System.Collections.Generic.Dictionary<string, string>(System.StringComparer.OrdinalIgnoreCase);
int stIdx = 1;
using DC_A95;
using ExternalDataSync;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using SystemFramework;
using WebApi;
namespace MesWork
{
/// <summary>
/// 程式启动
/// </summary>
public partial class MesWorkForm
{
/// <summary>
/// 从这里启动
/// </summary>
/// <param name="e"></param>
protected override void OnShown(EventArgs e)
{
}
public void OnStart(params object[] o)
{
//【1】系统基本参数设定
ThreadPool.SetMaxThreads(workerThreads, completionPortThreads);
Never_Know.Hello_You_All_Never_Know = Hello_You_All_Never_Know;
// 加载信号表(按设备类型对应表展开多工位)
var (dt_Tag_Mes, dt_Device) = BuildSignalTable(BasicDataTableFile);
// 保存工位名称列表及显示名映射供UC_Weighing标题使用
StationOpNames = new System.Collections.Generic.List<string>();
StationDisplayNames = new System.Collections.Generic.Dictionary<string, string>(System.StringComparer.OrdinalIgnoreCase);
int stIdx = 1;
foreach (System.Data.DataRow row in dt_Device.Rows)
{
string opName = row["工位号"].ToString().Trim();
@@ -48,87 +48,117 @@ namespace MesWork
StationDisplayNames[opName] = $"{opName}-{dataSource}";
stIdx++;
}
ValidateStationConfig();
LoadOPCData(dt_Tag_Mes, dt_Device, IsDemoMesServer, IsWriteMonitorLog, true, false, out string error);
if (error.Length > 0)
{
MessageBox.Show($"加载信号产生错误,程序不能启动!!错误:{error}");
Process.GetCurrentProcess().Kill();
}
Thread.Sleep(200);
StartServer();
Thread.Sleep(200);
First_TagMonitor();
var task1 = new Thread(new ThreadStart(Loop_SelectAlarmShow));
task1.IsBackground = true;
task1.Start();
// Loop_ReadRealPageShow 已移除PLC信号显示将在 UC_Weighing 中实现
// var task2 = new Thread(new ThreadStart(Loop_ReadRealPageShow));
// task2.IsBackground = true;
// task2.Start();
initServer = new InitServer(MesWorkForm.WebApi_Port);
if (error.Length > 0)
{
MessageBox.Show($"加载信号产生错误,程序不能启动!!错误:{error}");
Process.GetCurrentProcess().Kill();
}
Thread.Sleep(200);
StartServer();
Thread.Sleep(200);
First_TagMonitor();
var task1 = new Thread(new ThreadStart(Loop_SelectAlarmShow));
task1.IsBackground = true;
task1.Start();
// Loop_ReadRealPageShow 已移除PLC信号显示将在 UC_Weighing 中实现
// var task2 = new Thread(new ThreadStart(Loop_ReadRealPageShow));
// task2.IsBackground = true;
// task2.Start();
initServer = new InitServer(MesWorkForm.WebApi_Port);
B_DB_Opera.SaveLog_Request(Curr_Station, Log_Type.ZK_Login, "", Log_FromAndTo.ZK, Log_FromAndTo.ZK, $"称重系统启动成功WebPort:[{MesWorkForm.WebApi_Port}]", out long AID);
}
/// <summary>
/// 构建信号表读取Excel模板按「设备类型对应表」的工位配置展开
/// 每个工位独立克隆一份模板TagID加工位号前缀如 OP10_TAG_0000001
/// 并填充对应的 工位号、数据来源、IP、DB
/// 校验App.config中的逻辑工位必须能匹配Excel启用工位避免工位号配错后继续运行。
/// </summary>
/// <param name="excelFile">信号表Excel文件路径</param>
/// <returns>(展开后的信号表, 设备类型对应表)</returns>
private static (DataTable dtTagMes, DataTable dtDevice) BuildSignalTable(string excelFile)
private static void ValidateStationConfig()
{
// 读取设备类型对应表(所有启用的工位)
var dtDevice = NPOITest.ExeclHelper.ExcelToDataTable(excelFile, "设备类型对应表", true)
.Select("是否启用='1'").CopyToDataTable();
// 读取 MES_基本变量原始数据 模板(取全部启用行作为模板)
var dtTemplate = NPOITest.ExeclHelper.ExcelToDataTable(excelFile, "MES_基本变量原始数据", true)
.Select("是否启用='1'").CopyToDataTable();
// 按工位数量克隆模板
var dtTagMes = dtTemplate.Clone();
foreach (DataRow devRow in dtDevice.Rows)
string station1 = Station1OpName?.Trim();
string station2 = Station2OpName?.Trim();
if (string.IsNullOrWhiteSpace(station1) || string.IsNullOrWhiteSpace(station2))
{
string stationNo = devRow["工位号"].ToString().Trim(); // OP10, OP20
string dataSource = devRow["数据来源"].ToString().Trim(); // 称重位1, 称重位2
string deviceIP = devRow["设备IP"].ToString().Trim(); // 192.168.0.1
string deviceDB = devRow["DB"].ToString().Trim(); // DB1310, DB1311
// 提取纯DB号 ("DB1310" → "1310",若本身是数字则保持)
//string dbNumber = deviceDB.StartsWith("DB", StringComparison.OrdinalIgnoreCase)
// ? deviceDB.Substring(2) : deviceDB;
string dbNumber = deviceDB;
foreach (DataRow tplRow in dtTemplate.Rows)
{
var newRow = dtTagMes.NewRow();
for (int c = 0; c < dtTemplate.Columns.Count; c++)
newRow[c] = tplRow[c];
// 覆盖关键字段
newRow["TagID"] = $"{stationNo}_{tplRow["TagID"].ToString().Trim()}";
newRow["工位号"] = stationNo;
newRow["数据来源"] = dataSource;
newRow["IP"] = deviceIP;
newRow["DBName"] = dbNumber;
dtTagMes.Rows.Add(newRow);
}
MessageBox.Show("App.config未配置Station1OpName或Station2OpName程序不能启动。");
Process.GetCurrentProcess().Kill();
}
return (dtTagMes, dtDevice);
if (string.Equals(station1, station2, StringComparison.OrdinalIgnoreCase))
{
MessageBox.Show($"App.config中Station1OpName和Station2OpName不能相同当前均为[{station1}],程序不能启动。");
Process.GetCurrentProcess().Kill();
}
bool hasStation1 = StationOpNames.Exists(x => string.Equals(x, station1, StringComparison.OrdinalIgnoreCase));
bool hasStation2 = StationOpNames.Exists(x => string.Equals(x, station2, StringComparison.OrdinalIgnoreCase));
if (!hasStation1 || !hasStation2)
{
string excelStations = string.Join("、", StationOpNames);
MessageBox.Show($"App.config工位配置与SignalTable_CZ.xlsx不一致程序不能启动。\r\nStation1OpName={station1}\r\nStation2OpName={station2}\r\nExcel启用工位={excelStations}");
Process.GetCurrentProcess().Kill();
}
}
}
}
/// <summary>
/// 构建信号表读取Excel模板按「设备类型对应表」的工位配置展开
/// 每个工位独立克隆一份模板TagID加工位号前缀如 OP10_TAG_0000001
/// 并填充对应的 工位号、数据来源、IP、DB
/// </summary>
/// <param name="excelFile">信号表Excel文件路径</param>
/// <returns>(展开后的信号表, 设备类型对应表)</returns>
private static (DataTable dtTagMes, DataTable dtDevice) BuildSignalTable(string excelFile)
{
// 读取设备类型对应表(所有启用的工位)
var dtDevice = NPOITest.ExeclHelper.ExcelToDataTable(excelFile, "设备类型对应表", true)
.Select("是否启用='1'").CopyToDataTable();
// 读取 MES_基本变量原始数据 模板(取全部启用行作为模板)
var dtTemplate = NPOITest.ExeclHelper.ExcelToDataTable(excelFile, "MES_基本变量原始数据", true)
.Select("是否启用='1'").CopyToDataTable();
// 按工位数量克隆模板
var dtTagMes = dtTemplate.Clone();
foreach (DataRow devRow in dtDevice.Rows)
{
string stationNo = devRow["工位号"].ToString().Trim(); // OP10, OP20
string dataSource = devRow["数据来源"].ToString().Trim(); // 称重位1, 称重位2
string deviceIP = devRow["设备IP"].ToString().Trim(); // 192.168.0.1
string deviceDB = devRow["DB"].ToString().Trim(); // DB1310, DB1311
// 提取纯DB号 ("DB1310" → "1310",若本身是数字则保持)
//string dbNumber = deviceDB.StartsWith("DB", StringComparison.OrdinalIgnoreCase)
// ? deviceDB.Substring(2) : deviceDB;
string dbNumber = deviceDB;
foreach (DataRow tplRow in dtTemplate.Rows)
{
var newRow = dtTagMes.NewRow();
for (int c = 0; c < dtTemplate.Columns.Count; c++)
newRow[c] = tplRow[c];
// 覆盖关键字段
newRow["TagID"] = $"{stationNo}_{tplRow["TagID"].ToString().Trim()}";
newRow["工位号"] = stationNo;
newRow["数据来源"] = dataSource;
newRow["IP"] = deviceIP;
newRow["DBName"] = dbNumber;
dtTagMes.Rows.Add(newRow);
}
}
return (dtTagMes, dtDevice);
}
}
}