Files
2026-09-09 19:21:21 +08:00

2285 lines
99 KiB
C#
Raw Permalink 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 JinYuan.Helper;
using JinYuan.MES.Models;
using JinYuan.Models;
using JinYuan.VirtualDataLibrary;
using Language;
using MiniExcelLibs;
using PLC;
using PLC.PLCAlarm;
using PLCCommunication;
using PLCCommunication.Common;
using PLCCommunication.Common.DataConvert;
using PLCCommunication.PLCType.Siemens.S7PlusHelper;
using SqlSugar;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Runtime.CompilerServices.RuntimeHelpers;
using DataType = PLC.DataType;
namespace JinYuan.ControlCenters
{
public partial class ControlCenter : IDisposable
{
private static readonly object uiLock = new object();
private static ControlCenter _instance;
public static ControlCenter Instance
{
get
{
lock (uiLock)
{
return _instance ??= new ControlCenter();
}
}
}
private readonly Dictionary<string, PlcGroup> groups = new Dictionary<string, PlcGroup>();
private Dictionary<string, Func<JYResult<byte[]>, PlcGroup, Task>> stationFunctions;
//private Dictionary<string, Action<JYResult<byte[]>, PlcGroup>> stationFunctions;
private readonly Dictionary<PlcReadWriteBase, List<PlcDevice>> plcDeviceMapping = new Dictionary<PlcReadWriteBase, List<PlcDevice>>();
private readonly Dictionary<string, Task> groupTasks = new Dictionary<string, Task>();
private readonly Dictionary<PlcReadWriteBase, PLCAlarmReader> plcAlarmReaders = new Dictionary<PlcReadWriteBase, PLCAlarmReader>();
public CancellationTokenSource _cts;
private Task _heartbeatTask;
private const int HeartbeatInterval = 1000; // 1 second
/// <summary>
/// 定时器-定时刷新状态和数据
/// </summary>
private System.Timers.Timer Timer_RefreshData;
private readonly string configFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config");
private ControlCenter()
{
_cts = new CancellationTokenSource();
if (CommonMethods.plcDevices == null)
{
CommonMethods.plcDevices = new List<PlcReadWriteBase>();
}
InitializeDevicesFromExcel();
GetAlarmData();
InitFunc();
Timer_RefreshData = new System.Timers.Timer(1000);
Timer_RefreshData.Elapsed += Timer_RefreshData_Elapsed;
Timer_RefreshData.Start();
Thread thread = new Thread(ShowStateEven_Run);
thread.IsBackground = true;
thread.Start();
// 轴位置监控
//Task.Run(() => { ShowAxleEven_Run(); });
// 电机位置监控
//Task.Run(() => { ShowMotorEven_Run(); });
//Mes心跳监控
Task.Run(new Action(() => { UpdateMesHeartBeat(); }));
//删除30天内日志
//DeleteLog.Start(CommonMethods.strDeletepath);//会把整个ApiLog删除
string[] clrPath = new string[] { CommonMethods.strAlarmLogspath, CommonMethods.strMesLogspath, CommonMethods.strWattrMeterpath, @"D:\Logs\" };
short[] seltWay = new short[] { 0, 0, 0, 1 };
DeleteLog.Start(clrPath, seltWay);
if (!CommonMethods.IsRun)
{
CommonMethods.ResetEventRecv.Reset();
}
}
/// <summary>
/// 初始化 工位方法,添加到字典里面
/// </summary>
private void InitFunc()
{
stationFunctions = new Dictionary<string, Func<JYResult<byte[]>, PlcGroup, Task>>
{
["电芯进站A"] = FeedingStationA,
["电芯进站B"] = FeedingStationB,
["电芯出站A"] = BlankingStationA,
["电芯出站B"] = BlankingStationB,
//["结构件料盘"] = MaterialStation,
// 根据需要添加更多站点功能
};
}
public async Task StartAsync()
{
CreatePLCThreads();
_heartbeatTask = StartHeartbeatCheck(_cts.Token);
await Task.CompletedTask;
}
#region PLC
private void InitializeDevicesFromExcel()
{
CommonMethods.AddDataMonitorLog(1, "开始加载配置参数……".Translated());
string deviceConfigPath = Path.Combine(configFolderPath, "Device.xlsx");
string groupConfigPath = Path.Combine(configFolderPath, "Group.xlsx");
string variableConfigPath = Path.Combine(configFolderPath, "Variable.xlsx");
string plcVariableConfigPath = Path.Combine(configFolderPath, "PLCVariable.xlsx");
if (!File.Exists(deviceConfigPath) || !File.Exists(groupConfigPath) || !File.Exists(variableConfigPath))
{
LogHelper.Instance.WriteError("配置文件不存在");
return;
}
try
{
var deviceConfigs = MiniExcel.Query<PlcDevice>(deviceConfigPath).ToList();
var groupConfigs = MiniExcel.Query<PlcGroup>(groupConfigPath).ToList();
var variableConfigs = MiniExcel.Query<PlcVariable>(variableConfigPath).ToList();
var plcVariableConfigs = MiniExcel.Query<PLCGroupVariable>(plcVariableConfigPath).ToList();
ConcurrentDictionary<string, PLCGroupVariable> PLCVariable = new ConcurrentDictionary<string, PLCGroupVariable>();
if (plcVariableConfigs.Count > 0)
{
foreach (PLCGroupVariable variable in plcVariableConfigs)
{
if (variable.VarAddress != null && !variable.VarAddress.Equals(""))
{
PLCVariable.TryAdd(variable.VarAddress.Trim(), variable);
}
}
}
CommonMethods.PLCVariable = PLCVariable;
foreach (var deviceConfig in deviceConfigs.Where(d => d.IsActive))
{
IPEndPoint iep = new IPEndPoint(IPAddress.Parse(deviceConfig.IPAddress), deviceConfig.Port);
PlcReadWriteBase plc = PLCFactory.CreatePLC(GetPLCTypeEnum(deviceConfig.PLCType), deviceConfig.PlcNum, $"PLC_{deviceConfig.PlcNum}", iep);
deviceConfig.Cts = new CancellationTokenSource();
deviceConfig.GroupList = groupConfigs
.Where(g => g.IsActive && g.PlcNum == deviceConfig.PlcNum)
.ToList();
foreach (var group in deviceConfig.GroupList)
{
group.VarList = variableConfigs
.Where(v => v.GroupName == group.GroupName && v.PlcNum == deviceConfig.PlcNum)
.ToList();
}
plcDeviceMapping[plc] = new List<PlcDevice> { deviceConfig };
CommonMethods.plcDevices.Add(plc);
string tmp = AppDomain.CurrentDomain.BaseDirectory;
// 初始化 PLCAlarm Reader报警读取
var alarmReader = new PLCAlarmReader(
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AlarmConfig.csv"),
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AlarmRecords"),
RecordType.RecordWhenFinish,
false
);
//alarmReader.PLCAlarm_New += AlrmReader_PLCAlarm_New;
//alarmReader.PLCAlarm_Remove += AlrmReader_PLCAlarm_Remove;
//plcAlarmReaders[plc] = alarmReader;
//CommonMethods.plcStatuses[plc] = new Dictionary<string, object>
//{
// ["OldStatus"] = (short)0,
// ["StatusCount"] = 0,
// ["GuidAlarm"] = string.Empty,
// ["Status"] = new List<bool> { false, false, false, false }
//};
}
}
catch (Exception ex)
{
LogHelper.Instance.WriteError($"加载配置失败:{ex.Message}");
}
CommonMethods.AddDataMonitorLog(1, "配置文件加载完成".Translated());
}
#region 创建PLC线程 几个工位就几个线程
/// <summary>
/// 按工位读取线程
/// </summary>
///
private readonly Dictionary<string, Thread> groupThreads = new Dictionary<string, Thread>();
private readonly object lockObject = new object();
private void CreatePLCThreads()
{
for (int i = 0; i < CommonMethods.plcDevices.Count; i++)
{
var plc = CommonMethods.plcDevices[i];
if (plcDeviceMapping.TryGetValue(plc, out var plcDevices))
{
foreach (var plcDevice in plcDevices)
{
foreach (var plcGroup in plcDevice.GroupList.Where(g => g.IsActive))
{
string threadKey = $"{plcDevice.PlcNum}-{plcGroup.GroupName}";
var parameter = (group: plcGroup, plcIndex: i);
Thread thread = new Thread(new ParameterizedThreadStart(ReadPLCWorkModel));
thread.IsBackground = true;
thread.Priority = ThreadPriority.Highest;
lock (lockObject)
{
groupThreads[threadKey] = thread;
}
thread.Start(parameter);
}
}
}
}
}
#endregion
#region 循环读取PLC工位状态
/// <summary>
/// 读取PLC循环工位
/// </summary>
/// <param name="plcModel"></param>
private void ReadPLCWorkModel(object parameter)
{
if (parameter is ValueTuple<PlcGroup, int> tuple)
{
var (group, plcIndex) = tuple;
while (!_cts.Token.IsCancellationRequested)
{
if (CommonMethods.IsRun)
{
if (CommonMethods.plcDevices[plcIndex].IsConnected)
{
try
{
JYResult<short> OpenValue = CommonMethods.plcDevices[plcIndex].ReadValue<JYResult<short>>(group.VarList[0].VarAddress, DataType.Short);
if (OpenValue.IsSuccess && OpenValue.Content == 1)
{
JYResult<byte[]> resByte = CommonMethods.plcDevices[plcIndex].ReadValue<JYResult<byte[]>>($"{group.VarList[2].VarAddress}",
DataType.ArrByte, Convert.ToUInt16(group.VarList[2].OffsetOrLength));
CommonMethods.plcDevices[plcIndex].WriteInt16(group.VarList[0].VarAddress, (short)2);
if (resByte != null && stationFunctions.TryGetValue(group.GroupName, out var action))
{
Task.Run(() => action(resByte, group));
}
}
}
catch (Exception ex)
{
LogHelper.Instance.WriteError($"错误: {group.GroupName} - {ex.Message}", "SysErrorLog");
var bRet = CommonMethods.plcDevices[plcIndex].WriteInt16(group.VarList[0].VarAddress, (short)0);
LogHelper.Instance.WriteLog($"异常场景下,往{group.VarList[0].VarAddress}写0,写入是否成功:{bRet}", "PLC线程");
}
}
}
Thread.Sleep(100);
}
}
}
#endregion
#region 开始停止联机事件
/// <summary>
/// 开始联机
/// </summary>
/// <returns></returns>
public async Task<bool> ConnectAllPlcsAsync()
{
bool allConnected = true;
if (CommonMethods.plcDevices.Count <= 0)
{
CommonMethods.AddDataMonitorLog(1, "无PLC配置信息".Translated() + "," + "请检查配置文件".Translated());
return allConnected = false;
}
foreach (var plc in CommonMethods.plcDevices)
{
if (plcDeviceMapping.TryGetValue(plc, out var plcDevices))
{
foreach (var deviceConfig in plcDevices)
{
string msg = "";
try
{
// 使用 Task.Run 来在后台线程执行连接操作
bool isConnected = await Task.Run(() =>
{
// 设置一个连接超时
using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))) // 10秒超时
{
try
{
return plc.Connect(ref msg);
}
catch (OperationCanceledException)
{
msg = "连接超时";
return false;
}
}
});
deviceConfig.IsConnected = isConnected;
if (!deviceConfig.IsConnected)
{
allConnected = false;
LogHelper.Instance.WriteLog($"连接PLC失败: {deviceConfig.PlcNum}, 错误: {msg}");
CommonMethods.AddDataMonitorLog(1, "连接PLC失败".Translated() + $": {deviceConfig.PlcNum}, " + "错误".Translated() + $": {msg}");
}
else
{
CommonMethods.AddDataMonitorLog(0, "成功连接PLC".Translated() + $": {deviceConfig.PlcNum}");
}
}
catch (Exception ex)
{
allConnected = false;
LogHelper.Instance.WriteLog($"连接PLC时发生异常: {deviceConfig.PlcNum}, 错误: {ex.Message}");
CommonMethods.AddDataMonitorLog(2, "连接PLC时发生异常".Translated() + $": {deviceConfig.PlcNum}" + "错误".Translated() + $": {ex.Message}");
}
}
}
}
return allConnected;
}
/// <summary>
/// 断开链接
/// </summary>
public void DisconnectAllPlcs()
{
foreach (var plc in CommonMethods.plcDevices)
{
if (plcDeviceMapping.TryGetValue(plc, out var plcDevices))
{
foreach (var deviceConfig in plcDevices)
{
plc.Disconnect();
deviceConfig.IsConnected = false;
CommonMethods.AddDataMonitorLog(0, "已断开与PLC".Translated() + $"[{deviceConfig.PlcNum}]");
}
}
}
}
#endregion
#endregion
#region MES
/// <summary>
/// Mes心跳
/// </summary>
private void UpdateMesHeartBeat()
{
bool isNgral = false;
Thread.Sleep(100);
while (true)//true
{
try
{
if (CommonMethods.IsRun)//CommonMethods.mesConfig.isUpMes && CommonMethods.mesConfig.IsLoginMesOK &&
{
if (Ping() == true)
{
CommonMethods.mesConfig.isConnected = true;
if (!isNgral)
{
if (CommonMethods.plcDevices.Count > 0 && CommonMethods.plcDevices[0].IsConnected)
{
CommonMethods.plcDevices[0].WriteInt16("D80", (short)0);
}
string errStr = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")},Mes心跳Ping成功,IP:{CommonMethods.mesConfig.MESURLAddressIP},端口号:{CommonMethods.mesConfig.MESURLAddressPort}";
TxtHelper.WriteTxt($@"D:\APILog\Logs\MesLogs\{DateTime.Now.ToString("yyyyMMdd")}\Mes心跳报警\{DateTime.Now.ToString("HH")}.txt", errStr);
}
}
else//Ping失败,提示检查线路。
{
int count = 0;
bool mesOnLine = false;
do//重复3次
{
Thread.Sleep(1000);
if (Ping() == true) { mesOnLine = true; break; }
count++;
}
while (count < 3);
if (!mesOnLine)
{
CommonMethods.mesConfig.isConnected = false;
if (CommonMethods.plcDevices.Count > 0 && CommonMethods.plcDevices[0].IsConnected)
{
CommonMethods.plcDevices[0].WriteInt16("D80", (short)1);
}
isNgral = false;
string errStr = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")},Mes心跳Ping失败,IP:{CommonMethods.mesConfig.MESURLAddressIP},端口号:{CommonMethods.mesConfig.MESURLAddressPort}";
TxtHelper.WriteTxt($@"D:\APILog\Logs\MesLogs\{DateTime.Now.ToString("yyyyMMdd")}\Mes心跳报警\{DateTime.Now.ToString("HH")}.txt", errStr);
}
}
}
}
catch (Exception ex)
{
string errStr = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")},Mes心跳Ping异常,IP:{CommonMethods.mesConfig.MESURLAddressIP},端口号:{CommonMethods.mesConfig.MESURLAddressPort},原因:{ex.ToString()}";
TxtHelper.WriteTxt($@"D:\APILog\Logs\MesLogs\{DateTime.Now.ToString("yyyyMMdd")}\Mes心跳报警\{DateTime.Now.ToString("HH")}.txt", errStr);
}
Thread.Sleep(1000);
}
}
/// <summary>
/// Ping 检查网络线路问题
/// </summary>
/// <returns></returns>
public bool Ping()
{
try
{
string strIP = CommonMethods.mesConfig.MESURLAddressIP;
int port = Convert.ToInt32(CommonMethods.mesConfig.MESURLAddressPort);
IPAddress ip = IPAddress.Parse(strIP);
IPEndPoint _endPoint = new IPEndPoint(ip, port);
if (_endPoint.Address == null)
{
return false;
}
Ping _ping = new Ping();
int timeout = 1000;
PingReply mPingRcv = _ping.Send(_endPoint.Address, timeout);
return (mPingRcv.Status == IPStatus.Success) ? true : false;
}
catch (Exception ex)
{
string errStr = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")},Mes心跳Ping异常,IP:{CommonMethods.mesConfig.MESURLAddressIP},端口号:{CommonMethods.mesConfig.MESURLAddressPort},原因:{ex.ToString()}";
TxtHelper.WriteTxt($@"D:\APILog\Logs\MesLogs\{DateTime.Now.ToString("yyyyMMdd")}\Mes心跳报警\{DateTime.Now.ToString("HH")}.txt", errStr);
return false;
}
}
#endregion
#region 4、心跳和状态检查
/// <summary>
/// 心跳检测
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private async Task StartHeartbeatCheck(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
if (CommonMethods.IsRun)
{
foreach (var plc in CommonMethods.plcDevices)
{
if (plcDeviceMapping.TryGetValue(plc, out var plcDevices))
{
foreach (var plcDevice in plcDevices)
{
if (plcDevice.IsActive && plcDevice.IsHeartBeat)
{
await CheckHeartbeatForDevice(plc, plcDevice);
//await ShowStateEven_RunAsync();
}
}
}
}
}
await Task.Delay(HeartbeatInterval, cancellationToken);
}
}
/// <summary>
///
/// </summary>
/// <param name="plc"></param>
/// <param name="plcDevice"></param>
/// <returns></returns>
private async Task CheckHeartbeatForDevice(PlcReadWriteBase plc, PlcDevice plcDevice)
{
if (plcDevice.IsConnected)
{
JYResult result;
try
{
result = await Task.Run(() => plc.ReadValue<JYResult<short>>(plcDevice.HeartBeat, DataType.Short));
}
catch (Exception ex)
{
plcDevice.ErrorTimes++;
plcDevice.IsConnected = false;
LogHelper.Instance.WriteLog($"PLC编号:{plcDevice.PlcNum} 读取心跳异常:{ex.Message}!!!");
return;
}
if (result.IsSuccess)
{
plcDevice.ErrorTimes = 0;
JYResult res;
try
{
res = await Task.Run(() => plc.WriteValue(plcDevice.HeartBeat, (short)1, DataType.Short));
}
catch (Exception ex)
{
plcDevice.IsConnected = false;
LogHelper.Instance.WriteError($"PLC编号:{plcDevice.PlcNum} 写入心跳异常:{ex.Message}!!!");
return;
}
if (!res.IsSuccess)
{
plcDevice.IsConnected = false;
LogHelper.Instance.WriteError($"PLC编号:{plcDevice.PlcNum}=心跳写入异常:{res.Message}!!!");
}
}
else
{
HandleHeartbeatFailure(plcDevice, result);
}
}
else
{
await ReconnectDevice(plc, plcDevice);
}
}
private void HandleHeartbeatFailure(PlcDevice plcDevice, JYResult result)
{
plcDevice.ErrorTimes++;
plcDevice.IsConnected = false;
if (plcDevice.ErrorTimes >= plcDevice.AllowErrorTimes)
{
LogHelper.Instance.WriteError($"编号:[{plcDevice.PlcNum}]的PLC链接断开:{result.Message}");
}
}
private async Task ReconnectDevice(PlcReadWriteBase plc, PlcDevice plcDevice)
{
if (!plcDevice.IsFirstConnect)
{
await Task.Delay(plcDevice.ReConnectTime);
try { plc.Disconnect(); }
catch (Exception ex)
{
LogHelper.Instance.WriteError($"编号:[{plcDevice.PlcNum}]的PLC断开链接异常:{ex.Message}");
}
}
string msg = "";
bool connectResult = false;
try
{
connectResult = await Task.Run(() => plc.Connect(ref msg));
}
catch (Exception ex)
{
msg = ex.Message;
connectResult = false;
}
plcDevice.IsConnected = connectResult;
LogHelper.Instance.WriteError(connectResult
? $"PLC编号:{plcDevice.PlcNum}{(plcDevice.IsFirstConnect ? "初次" : "重新")}连接成功{msg}!"
: $"[{plcDevice.PlcNum}]#PLC{(plcDevice.IsFirstConnect ? "初次" : "重新")}连接失败{msg}!");
plcDevice.IsFirstConnect = false;
}
#endregion
#region 定时刷新数据
int TotalNum = 0;
int TotalNum1 = 0;
int Regular = 0;
int JetBeat = 0;
private void Timer_RefreshData_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (Regular >= 300)
{
Task.Run(() =>
{
GetEnergyData();
UploadEquEnergy();//能耗
//ReUpProducResultParam();//定时补传
});
Regular = 0;
}
if (TotalNum > 4)
{
//GetEnergyData();
Task.Run(() =>
{
Thread.Sleep(50);
Refresh12HourProdQty();
});
GetDefectTypeQty();
ReadPLCComm();
GetASqlAlarmData(DateTime.Today, CommonMethods.strClass);
TotalNum = 0;
}
else if (TotalNum == 2)//设备状态读取
{
SetClass(); //变更班次
}
//Task.Run(() =>
//{
// ShowStateEven_Run();
//});
if (TotalNum1 >= 3600 * 24)
{
Task.Run(() =>
{
DeleteFileOfLocal();
DeleteDataOfReInBgearentity();
});
TotalNum1 = 0;
}
//电能表心跳
//if (JetBeat > 5)
//{
//if (!CommonMethods.energyMeter.Connected)
//{
//CommonMethods.energyMeter.SetTCPParams(IPAddress.Parse("192.168.1.25"), 502);
//CommonMethods.energyMeter.Connect();
//}
//JetBeat = 0;
//}
//JetBeat++;
TotalNum++;
TotalNum1++;
Regular++;
}
#endregion
#region 设备综合信息
/// <summary>
/// 读取PLC通用信息
/// </summary>
internal void ReadPLCComm()
{
if (CommonMethods.plcDevices.Count != 0 && CommonMethods.plcDevices[0].IsConnected)
{
Task.Run(async () =>
{
await UpTotalCount(null);
Thread.Sleep(50);
});
CommonMethods.TotalQty = CommonMethods.plcDevices[0].ReadFloat("D15");//生产总数
CommonMethods.ProOKQty = CommonMethods.plcDevices[0].ReadFloat("D17");//良品总数
CommonMethods.Ppm = CommonMethods.plcDevices[0].ReadFloat("D13");
CommonMethods.JiaDL = Convert.ToDouble(CommonMethods.plcDevices[0].ReadFloat("D11").ToString("F2"));
#region 开机时间/运行时间
CommonMethods.PlcOpenAndRunTime = GetList<int>(6, 0);
JYResult<byte[]> resByte = CommonMethods.plcDevices[0].ReadValue<JYResult<byte[]>>($"D50", DataType.ArrByte, 12);
if (resByte.IsSuccess && resByte.Content.Length >= 24)
{
for (int i = 0; i < CommonMethods.PlcOpenAndRunTimeAdress.Count; i++)
{
CommonMethods.PlcOpenAndRunTime[i] = IntLib.GetIntFromByteArray(resByte.Content, i * 4, DataFormat.CDAB);//ShortLib.GetShortFromByteArray(resByte.Content, i * 4, DataFormat.CDAB);
}
}
#endregion
}
}
#endregion
#region 保存12小时产能数据
public int totalNum = 0; // 总数
public int okNum = 0; // 良品数
/// <summary>
/// 储存数据到数据库
/// </summary>
/// <param name="DataCount"></param>
public async Task UpTotalCount(int[] DataCount)
{
try
{
DateTime dateTime = DateTime.Now;
string strDate = dateTime.ToString("yyyy-MM-dd");
// 获取当前时间的小时和分钟
int currentHour = dateTime.Hour;
int currentMinute = dateTime.Minute;
// 根据当前分钟确定统计小时
// 如果当前时间在 X:30 之前,则统计的是前一个小时的数据(从前一个小时的30分到这个小时的29分)
// 如果当前时间在 X:30 之后,则统计的是当前小时的数据(从当前小时的30分到下个小时的29分)
int statisticalHour;
if (currentMinute < 30)
{
statisticalHour = (currentHour + 23) % 24; // 前一个小时,处理跨天的情况
// 如果是凌晨0点前的数据,需要使用前一天的日期
if (currentHour == 0)
{
strDate = dateTime.AddDays(-1).ToString("yyyy-MM-dd");
}
}
else
{
statisticalHour = currentHour;
}
// 数据有效性验证
if (statisticalHour < 0 || statisticalHour > 23)
{
throw new ArgumentException($"无效的小时值: {statisticalHour}");
}
//读取统计小时的PLC投入总数和产出数
int ProdCurrAllQty = GetToDayHourQty(statisticalHour, true);
int ProdCurrOKQty = GetToDayHourQty(statisticalHour, false);
// 确保数量为非负数
if (ProdCurrAllQty < 0 || ProdCurrOKQty < 0)
{
LogHelper.Instance.WriteError($"产量不能为负数: 投入={ProdCurrAllQty}, 产出={ProdCurrOKQty}");
//throw new ArgumentException($"产量不能为负数: 投入={ProdCurrAllQty}, 产出={ProdCurrOKQty}");
}
Hourprod mh = new Hourprod
{
FDate = strDate,
FHour = statisticalHour,
ProdIn = ProdCurrAllQty,
ProdOut = ProdCurrOKQty,
TestTime = dateTime,
Ppm = (int)CommonMethods.Ppm,
JiaDL = Convert.ToDecimal(CommonMethods.JiaDL)
};
// 尝试更新记录
int res = CommonMethods.db.UpdateSingle(
mh,
it => new Hourprod
{
ProdIn = mh.ProdIn,
ProdOut = mh.ProdOut,
TestTime = mh.TestTime,
Ppm = mh.Ppm,
JiaDL = mh.JiaDL
},
it => it.FDate == mh.FDate && it.FHour == mh.FHour
);
// 如果更新失败(记录不存在),则新增记录
if (res <= 0)
{
bool addResult = await CommonMethods.db.AddReturnBoolAsync<Hourprod>(mh);
if (!addResult)
{
LogHelper.Instance.WriteError($"保存小时产能新增记录失败");
}
}
// 可以添加日志记录成功信息
// Logger.Log($"成功更新/新增产能数据: 日期={strDate}, 小时={statisticalHour}, 时段={statisticalHour}:30~{(statisticalHour + 1) % 24}:29");
}
catch (Exception ex)
{
// 这里应该添加错误日志记录
LogHelper.Instance.WriteEX($"保存小时产能数据失败: ", ex);
}
}
//string strErr = "";
//DateTime dateTime = DateTime.Now;
//string strDate = dateTime.ToString("yyyy-MM-dd");
//int Min = dateTime.Minute;
//int Hour = dateTime.Hour;
//if (Min < 30)
//{
// Hour -= 1;
//}
//if (dateTime.Hour < 30 && dateTime.Hour == 0)
//{
// Hour = 0;
//}
////读取PLC投入总数
//int ProdCurrAllQty = GetToDayHourQty(Hour, true);
////读取PLC产出数
//int ProdCurrOKQty = GetToDayHourQty(Hour, false);
//Hourprod mh = new Hourprod();
//mh.FDate = strDate;
//mh.FHour = Hour;
//mh.ProdIn = ProdCurrAllQty;
//mh.ProdOut = ProdCurrOKQty;
//mh.TestTime = DateTime.Now;
//mh.Ppm = CommonMethods.Ppm;
//mh.JiaDL = Convert.ToDecimal(CommonMethods.JiaDL);
////更新
//int res = CommonMethods.db.UpdateSingle(mh, it => new Hourprod() { ProdIn = mh.ProdIn, ProdOut = mh.ProdOut, TestTime = DateTime.Now, Ppm = mh.Ppm, JiaDL = mh.JiaDL, },
// it => it.FDate == mh.FDate && it.FHour == mh.FHour);
//if (res <= 0) //更新失败就新增保存
//{
// CommonMethods.db.AddReturnBool<Hourprod>(mh);
//}
/// <summary>
/// 每小时产能读取处理
/// </summary>
/// <param name="hour"></param>
/// <param name="flag"></param>
/// <returns></returns>
private int GetToDayHourQty(int hour, bool flag)
{
try
{
string strAddr = "";
if (flag)//产出
{
strAddr = "D" + (1040 + hour);
}
else//良品数
{
strAddr = "D" + (1070 + hour);
}
int ProdNGQty = CommonMethods.plcDevices[0].ReadInt16(strAddr);
return ProdNGQty;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "系统异常", MessageBoxButtons.OK, MessageBoxIcon.Hand);
}
return 0;
}
#endregion
#region 5、设备状态
/// <summary>
/// 定时获取设备状态
/// </summary>
/// <param name="mt"></param>
///
int OldStatues = Convert.ToInt32(IniConfigHelper.ReadIniData("上一次设备状态", "DeviceStatus", "1", CommonMethods.strDeviceStatusPath));//退出程序前设备状态
int StatuesCount = 0;
DateTime StatuesBeginTime = DateTime.Now.AddMinutes(-6);
string strGuidAlarm = IniConfigHelper.ReadIniData("上一次Guid", "DeviceGuid", Guid.NewGuid().ToString(), CommonMethods.strDeviceStatusPath);//退出程序前Guid
bool run_AlarmMark = false;//特殊情况1标志(运行状态)
bool run_IdleMark = false;//特殊情况2标志(闲置状态)
bool isUpIdleAlarm = false;//闲置状态报警信息上传标志
List<AlarmData> idleAlarmData = new List<AlarmData>();//闲置状态的报警信息
private async void ShowStateEven_Run()
{
while (true)
{
try
{
if (CommonMethods.plcDevices.Count > 0 && CommonMethods.plcDevices != null)
{
if (CommonMethods.plcDevices[0] != null && CommonMethods.plcDevices[0].IsConnected)
{
DateTime Date = DateTime.Now;
bool isUpload = false;
string deviceStatus = string.Empty;
string deviceStatusDesc = string.Empty;
short NewStatus = CommonMethods.plcDevices[0].ReadInt16("D10");
if (NewStatus != 100)
{
//特殊情况1:运行->报警->……->运行
if (NewStatus == 3 && OldStatues == 1) { run_AlarmMark = true; }//第一次进入报警状态
if (NewStatus == 1) { run_AlarmMark = false; }//下一次运行状态,置位
if (run_AlarmMark) { NewStatus = 3; }//报警状态后下一次运行状态期间一直是报警状态
//特殊情况2:运行->闲置->……->运行
if (NewStatus == 4 && OldStatues == 1) { run_IdleMark = true; }//第一次进入闲置状态
if (NewStatus == 1) { run_IdleMark = false; }//下一次闲置状态,置位
if (run_IdleMark) { NewStatus = 4; }//闲置状态后下一次运行状态期间一直是闲置状态
//闲置状态结束报警信息上传
if (OldStatues == 4 && NewStatus != 4 && isUpIdleAlarm)
{
_ = UpIdleDataAsync(idleAlarmData, strGuidAlarm);
}
//设备状态信号灯变量
CommonMethods.Statues = new List<bool> { NewStatus == 1, NewStatus == 2, NewStatus == 3, NewStatus == 4 };
// 状态切换时生成新的 GUID
if (NewStatus != OldStatues)
{
// 从 Alert 切换到非 Alert 状态时,上传报警信息
if (OldStatues == 3 && NewStatus != 3)
{
ShowAlarmEven_Run(strGuidAlarm, NewStatus);
}
// 只要状态变更,就生成新的 GUID
strGuidAlarm = Guid.NewGuid().ToString(); // 强制生成新的 GUID
isUpload = true;
//StatuesCount = 0;
OldStatues = NewStatus;
StatuesBeginTime = Convert.ToDateTime(Date);
//记录最新设备状态和Guid
//CommonMethods.UpdateConfig("MES_CONFIG", "DeviceStatus", NewStatus.ToString());// 保存设备状态到xml文件
//CommonMethods.UpdateConfig("MES_CONFIG", "Guid", strGuidAlarm);// 保存设备状态到xml文件
//CommonMethods.Configxml["MES_CONFIG"]["DeviceStatus"] = NewStatus.ToString(); // 保存设备状态到xml文件
//CommonMethods.Configxml["MES_CONFIG"]["Guid"] = strGuidAlarm; // 保存设备状态到xml文件
//CommonMethods.WriteXmlFile(CommonMethods.Configxml, CommonMethods.xmlFilePath);
IniConfigHelper.WriteIniData("上一次设备状态", "DeviceStatus", NewStatus.ToString(), CommonMethods.strDeviceStatusPath);
IniConfigHelper.WriteIniData("上一次Guid", "DeviceGuid", strGuidAlarm, CommonMethods.strDeviceStatusPath);
}
else
{
// 同种状态持续 5 分钟时上传状态信息
//StatuesCount++;
//if (StatuesCount >= 5 * 60)
//{
// isUpload = true;
// StatuesCount = 0;
//}
if (Date.Subtract(StatuesBeginTime).TotalSeconds < 5 * 60 && Date.Subtract(StatuesBeginTime).TotalSeconds >= 4 * 60)
{
isUpload = true;
StatuesBeginTime = DateTime.Now;
}
}
// 根据状态设置设备状态和描述
switch (NewStatus)
{
case 1:
deviceStatus = "Run";
deviceStatusDesc = "正常运行";
break;
case 2://取消
deviceStatus = "Maintain";
deviceStatusDesc = "停止运行";
break;
case 3:
deviceStatus = "Alert";
deviceStatusDesc = "故障调试";
// Alert 状态时上传报警信息
ShowAlarmEven_Run(strGuidAlarm, NewStatus);
break;
case 4:
deviceStatus = "Idle";
deviceStatusDesc = "闲置待机";
ShowStuesEven_Run(strGuidAlarm);
break;
}
// 上传设备状态信息
if (CommonMethods.sysConfig.MesModeSwitching && CommonMethods.mesConfig.isConnected && isUpload && (NewStatus == 1 || NewStatus == 3 || NewStatus == 4))
{
var (success, message) = await CommonMethods.hbgMes.UploadEquStatusAsync(
CommonMethods.mesConfig.DeviceStatus,
CommonMethods.mesConfig.siteCode,
CommonMethods.mesConfig.lineCode,
CommonMethods.mesConfig.equipNum,
CommonMethods.mesConfig.MaterialCode,
CommonMethods.mesConfig.mesUserName,
strGuidAlarm, // RUN 状态时传空
deviceStatus,
null
);
if (success)
{
StatuesCount = 0;
}
}
}
}
}
}
catch (Exception ex)
{
LogHelper.Instance.WriteEX(ex);
}
Thread.Sleep(100);
}
}
#region 触摸屏弹窗
private async void ShowStuesEven_Run(string strGuid)
{
if (CommonMethods.plcDevices[0].IsConnected)
{
string strCode = "";
string alarmName = "";
short HMIStatus = CommonMethods.plcDevices[0].ReadInt16("D40");
if (HMIStatus != 0)
{
CommonMethods.AddDataMonitorLog(0, "触发了手动HMI弹窗功能".Translated());
switch (HMIStatus) //注意:B1-D12都为闲置代码,上传代码是只需上传闲置代码
{
//case 1://取消
// strCode = "B1";
// alarmName = "计划维保";
// CommonMethods.AddDataMonitorLog(0, "B1 计划维保");
// break;
//case 2://取消
// strCode = "B2";
// alarmName = "无生产计划";
// CommonMethods.AddDataMonitorLog(0, "B2 无生产计划");
// break;
//case 3://取消
// strCode = "B3";
// alarmName = "样品、试产";
// CommonMethods.AddDataMonitorLog(0, "B3 样品、试产");
// break;
//case 4://取消
// strCode = "B4";
// alarmName = "其他计划停机";
// CommonMethods.AddDataMonitorLog(0, "B4.其他计划停机");
// break;
case 5:
strCode = "D1";
alarmName = "设备故障".Translated();
CommonMethods.AddDataMonitorLog(0, $"{strCode} {alarmName}");
break;
case 6:
strCode = "D2";
alarmName = "设备转型".Translated();
CommonMethods.AddDataMonitorLog(0, $"{strCode} {alarmName}");
break;
case 7:
strCode = "D3";
alarmName = "工程变更".Translated();
CommonMethods.AddDataMonitorLog(0, $"{strCode} {alarmName}");
break;
case 8:
strCode = "D4";
alarmName = "MES停机".Translated();
CommonMethods.AddDataMonitorLog(0, $"{strCode} {alarmName}");
break;
case 9:
strCode = "D5";
alarmName = "品质异常".Translated();
CommonMethods.AddDataMonitorLog(0, $"{strCode} {alarmName}");
break;
case 10:
strCode = "D6";
alarmName = "配件,物料更换".Translated();
CommonMethods.AddDataMonitorLog(0, $"{strCode} {alarmName}");
break;
case 11:
strCode = "D7";
alarmName = "来料不良".Translated();
CommonMethods.AddDataMonitorLog(0, $"{strCode} {alarmName}");
break;
case 12:
strCode = "D8";
alarmName = "待料".Translated();
CommonMethods.AddDataMonitorLog(0, $"{strCode} {alarmName}");
break;
case 13:
strCode = "D9";
alarmName = "品质检查".Translated();
CommonMethods.AddDataMonitorLog(0, $"{strCode} {alarmName}");
break;
case 14:
strCode = "D10";
alarmName = "清洁点检".Translated();
CommonMethods.AddDataMonitorLog(0, $"{strCode} {alarmName}");
break;
case 15:
strCode = "D11";
alarmName = "环境不满足".Translated();
CommonMethods.AddDataMonitorLog(0, $"{strCode} {alarmName}");
break;
case 16:
strCode = "D12";
alarmName = "其它非计划停机".Translated();
CommonMethods.AddDataMonitorLog(0, $"{strCode} {alarmName}");
break;
default:
break;
}
if (CommonMethods.sysConfig.MesModeSwitching && CommonMethods.mesConfig.isConnected)
{
List<AlarmData> alarmObj = new List<AlarmData>();
AlarmData alarmData = new AlarmData();
alarmData.AlarmCode = strCode;
alarmData.StartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
alarmData.EndTime = "";
alarmData.AlarmType = "非计划损失";
alarmData.AlarmContent = alarmName;
alarmObj.Add(alarmData);
//闲置报警上传标志
isUpIdleAlarm = true;
idleAlarmData.Add(alarmData);
//上传报警
var (success, message) = await CommonMethods.hbgMes.UploadEquAlarmAsync(CommonMethods.mesConfig.DeviceAlarm, CommonMethods.mesConfig.siteCode, CommonMethods.mesConfig.lineCode,
CommonMethods.mesConfig.equipNum, CommonMethods.mesConfig.MaterialCode, CommonMethods.mesConfig.mesUserName, alarmObj, strGuid);
if (success)
CommonMethods.AddDataMonitorLog(0, "HMI手动弹窗状态已上传成功,代码".Translated() + $":{strCode}");
}
bool IsSuccess = CommonMethods.plcDevices[0].WriteInt16("D40", 0);
if (IsSuccess)
CommonMethods.AddDataMonitorLog(0, $"D40已复位0".Translated());
}
}
}
#endregion
/// <summary>
/// HMI手动弹窗结束状态上传
/// </summary>
/// <param name="idleAlarmDate"></param>
/// <param name="strGuidAlarm"></param>
/// <returns></returns>
private async Task UpIdleDataAsync(List<AlarmData> idleAlarmDate, string strGuidAlarm)
{
if (idleAlarmDate.Count == 0) { return; }
string strCode = "";
foreach (var item in idleAlarmDate)
{
item.EndTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
strCode = item.AlarmCode + ",";
}
if (CommonMethods.sysConfig.MesModeSwitching && CommonMethods.mesConfig.isConnected)
{
//上传报警
var (success, message) = await CommonMethods.hbgMes.UploadEquAlarmAsync(CommonMethods.mesConfig.DeviceAlarm, CommonMethods.mesConfig.siteCode, CommonMethods.mesConfig.lineCode,
CommonMethods.mesConfig.equipNum, CommonMethods.mesConfig.MaterialCode, CommonMethods.mesConfig.mesUserName, idleAlarmDate, strGuidAlarm);
if (success)
CommonMethods.AddDataMonitorLog(0, "HMI手动弹窗结束状态已上传成功,代码".Translated() + $":{strCode.TrimEnd(',')}");
}
idleAlarmData.Clear();
isUpIdleAlarm = false;
}
#endregion
#region 6、设备报警
//报警表单数据
List<AlarmForm> listAlarmForm = null;
public void GetAlarmData()
{
//加载PLC报警文件
try
{
string strFileName = System.Environment.CurrentDirectory + "\\欧姆龙报警寄存器对应表.csv";
listAlarmForm = CSVHelper<AlarmForm>.ReadCSV<AlarmForm>(strFileName);
}
catch (Exception ex)
{
MessageBox.Show("加载报警文件失败!");
}
}
/// <summary>
/// 报警信息读取
/// </summary>
/// <param name="mt"></param>
/// <param name="resByte"></param>
List<AlarmData> listOld = new List<AlarmData>();
List<AlarmData> listNew = new List<AlarmData>();
private void ShowAlarmEven_Run(string strGuidAlarm,int MachineState)
{
if (!CommonMethods.IsRun || !CommonMethods.plcDevices[0].IsConnected)
{
return;
}
try
{
// 1. 读取 PLC 报警信息
List<AlarmStatus> alarmStatusList = ReadAlarmStatusFromPLC();
if (alarmStatusList == null || listAlarmForm == null)//true
{
return;
}
// 2. 解析报警信息并生成新的报警列表
List<AlarmData> newAlarms = ParseAlarmStatus(alarmStatusList, strGuidAlarm);
if (newAlarms.Count > 0)
{
// 3. 检测新报警并添加到旧报警列表,上传第一次报警信息
DetectNewAlarmsAsync(newAlarms);
// 4. 文字显示新报警信息
DisplayAlarmInfo(newAlarms);
}
// 5. 检测已取消的报警并处理
List<AlarmData> canceledAlarms = DetectCanceledAlarms(newAlarms);
if (canceledAlarms.Count > 0)
{
// 6. 记录已取消的报警信息(保存本地)
LogCanceledAlarms(canceledAlarms);
// 7. 上传已取消的报警信息(报警结束上传一次)
UploadCanceledAlarmsAsync(canceledAlarms, strGuidAlarm);
}
if (MachineState != 3 && listOld.Count > 0) //设备状态变为非报警并旧报警仍有报警。旧报警上传并清空
{
List<AlarmData> tempOldAlarmList = new List<AlarmData>();
foreach (var item in listOld)
{
item.EndTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); //所有报警全部结束时间赋值
tempOldAlarmList.Add(item);
}
// 6. 记录已取消的报警信息(保存本地)
LogCanceledAlarms(tempOldAlarmList);
// 7. 上传已取消的报警信息(报警结束上传一次)
UploadCanceledAlarmsAsync(tempOldAlarmList, strGuidAlarm);
listOld.Clear();
}
}
catch (Exception ex)
{
LogHelper.Instance.WriteEX(ex);
}
}
/// <summary>
/// 从 PLC 读取报警状态
/// </summary>
private List<AlarmStatus> ReadAlarmStatusFromPLC()
{
//string Date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
//JYResult<byte[]> resByte = CommonMethods.plcDevices[0].ReadValue<JYResult<byte[]>>("D10150", DataType.ArrByte, 5000);
//if (resByte.IsSuccess && resByte != null)
//{
// int startPlcAddr = 10150; // 读取起始地址
// return PLCAlarmParseHelper.OmronFinsByte2Status(startPlcAddr, resByte.Content);
//}
string Date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
// 读取足够的字节覆盖所有可能的报警地址
int startAddr = 10150;
int endAddr = 14750; // 根据实际最大地址调整
int wordCount = endAddr - startAddr + 1;
int byteCount = wordCount * 2; // 每个字2字节
JYResult<byte[]> resByte = CommonMethods.plcDevices[0].ReadValue<JYResult<byte[]>>(
$"D{startAddr}", DataType.ArrByte, (ushort)byteCount);
if (resByte.IsSuccess && resByte.Content != null)
{
return PLCAlarmParseHelper.OmronFinsByte2Status(startAddr, resByte.Content);
}
return null;
}
/// <summary>
/// 解析报警状态并生成新的报警列表
/// </summary>
private List<AlarmData> ParseAlarmStatus(List<AlarmStatus> alarmStatusList, string strGuidAlarm)
{
string Date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
var alarmTypeMap = new Dictionary<char, string> // 定义报警类型映射字典
{
{'1', "停机报警"},
{'2', "非停机报警"},
};
switch (LanguageManager.LanguageCode)
{
case "en"://英语报警信息
return alarmStatusList
.Where(status => status.Status)
.Join(
listAlarmForm,
status => status.PLCAdress,
form => form.PLCAdress,
(status, form) =>
{
var alarmContent = string.IsNullOrEmpty(form.EnAlarmContent)
? status.PLCAdress
: form.EnAlarmContent;
string alarmType = "停机报警"; // 默认值
if (form.AlarmCode?.Length >= 3)
{
char thirdChar = form.AlarmCode[2];
// 尝试从字典获取对应的值
if (alarmTypeMap.TryGetValue(thirdChar, out string mappedType))
{
alarmType = mappedType;
}
}
return new AlarmData
{
AlarmGuid = strGuidAlarm,
PLCAdress = status.PLCAdress,
AlarmCode = form.AlarmCode,
AlarmContent = alarmContent,
AlarmType = alarmType,
AlarmDesc = alarmContent,
AlarmState = "1",
StartTime = Date,
EndTime = "",
Flag = 0
};
})
.ToList();
case "hu"://匈牙利语报警信息
return alarmStatusList
.Where(status => status.Status)
.Join(
listAlarmForm,
status => status.PLCAdress,
form => form.PLCAdress,
(status, form) =>
{
var alarmContent = string.IsNullOrEmpty(form.HuAlarmContent)
? status.PLCAdress
: form.HuAlarmContent;
string alarmType = "停机报警"; // 默认值
if (form.AlarmCode?.Length >= 3)
{
char thirdChar = form.AlarmCode[2];
// 尝试从字典获取对应的值
if (alarmTypeMap.TryGetValue(thirdChar, out string mappedType))
{
alarmType = mappedType;
}
}
return new AlarmData
{
AlarmGuid = strGuidAlarm,
PLCAdress = status.PLCAdress,
AlarmCode = form.AlarmCode,
AlarmContent = alarmContent,
AlarmType = alarmType,
AlarmDesc = alarmContent,
AlarmState = "1",
StartTime = Date,
EndTime = "",
Flag = 0
};
})
.ToList();
case "ms"://马来语报警信息
return alarmStatusList
.Where(status => status.Status)
.Join(
listAlarmForm,
status => status.PLCAdress,
form => form.PLCAdress,
(status, form) =>
{
var alarmContent = string.IsNullOrEmpty(form.MsAlarmContent)
? status.PLCAdress
: form.MsAlarmContent;
string alarmType = "停机报警"; // 默认值
if (form.AlarmCode?.Length >= 3)
{
char thirdChar = form.AlarmCode[2];
// 尝试从字典获取对应的值
if (alarmTypeMap.TryGetValue(thirdChar, out string mappedType))
{
alarmType = mappedType;
}
}
return new AlarmData
{
AlarmGuid = strGuidAlarm,
PLCAdress = status.PLCAdress,
AlarmCode = form.AlarmCode,
AlarmContent = alarmContent,
AlarmType = alarmType,
AlarmDesc = alarmContent,
AlarmState = "1",
StartTime = Date,
EndTime = "",
Flag = 0
};
})
.ToList();
case "zh":
default:
return alarmStatusList
.Where(status => status.Status)
.Join(
listAlarmForm,
status => status.PLCAdress,
form => form.PLCAdress,
(status, form) =>
{
var alarmContent = string.IsNullOrEmpty(form.AlarmContent)
? status.PLCAdress
: form.AlarmContent;
string alarmType = "停机报警"; // 默认值
if (form.AlarmCode?.Length >= 3)
{
char thirdChar = form.AlarmCode[2];
// 尝试从字典获取对应的值
if (alarmTypeMap.TryGetValue(thirdChar, out string mappedType))
{
alarmType = mappedType;
}
}
return new AlarmData
{
AlarmGuid = strGuidAlarm,
PLCAdress = status.PLCAdress,
AlarmCode = form.AlarmCode,
AlarmContent = alarmContent,
AlarmType = alarmType,
AlarmDesc = alarmContent,
AlarmState = "1",
StartTime = Date,
EndTime = "",
Flag = 0
};
})
.ToList();
};
/*switch (LanguageManager.LanguageCode)
{
case "en"://英语报警信息
return alarmStatusList
.Where(s => s.Status)
.Join(listAlarmForm, s => s.PLCAdress, f => f.PLCAdress, (s, f) => new AlarmData()
{
AlarmGuid = strGuidAlarm,
PLCAdress = s.PLCAdress,
AlarmCode = f.AlarmCode,
AlarmContent = f.EnAlarmContent == "" ? s.PLCAdress : f.EnAlarmContent,
AlarmType = "停机报警",
AlarmDesc = f.EnAlarmContent == "" ? s.PLCAdress : f.EnAlarmContent,
AlarmState = "1",
StartTime = Date,
EndTime = "",//Date
Flag = 0
}).ToList();
case "hu"://匈牙利语报警信息
return alarmStatusList
.Where(s => s.Status)
.Join(listAlarmForm, s => s.PLCAdress, f => f.PLCAdress, (s, f) => new AlarmData()
{
AlarmGuid = strGuidAlarm,
PLCAdress = s.PLCAdress,
AlarmCode = f.AlarmCode,
AlarmContent = f.HuAlarmContent == "" ? s.PLCAdress : f.HuAlarmContent,
AlarmType = "停机报警",
AlarmDesc = f.HuAlarmContent == "" ? s.PLCAdress : f.HuAlarmContent,
AlarmState = "1",
StartTime = Date,
EndTime = "",//Date
Flag = 0
}).ToList();
case "ms"://马来语报警信息
return alarmStatusList
.Where(s => s.Status)
.Join(listAlarmForm, s => s.PLCAdress, f => f.PLCAdress, (s, f) => new AlarmData()
{
AlarmGuid = strGuidAlarm,
PLCAdress = s.PLCAdress,
AlarmCode = f.AlarmCode,
AlarmContent = f.MsAlarmContent == "" ? s.PLCAdress : f.MsAlarmContent,
AlarmType = "停机报警",
AlarmDesc = f.MsAlarmContent == "" ? s.PLCAdress : f.MsAlarmContent,
AlarmState = "1",
StartTime = Date,
EndTime = "",//Date
Flag = 0
}).ToList();
case "zh"://中语报警信息
default:
return alarmStatusList
.Where(s => s.Status)
.Join(listAlarmForm, s => s.PLCAdress, f => f.PLCAdress, (s, f) => new AlarmData()
{
AlarmGuid = strGuidAlarm,
PLCAdress = s.PLCAdress,
AlarmCode = f.AlarmCode,
AlarmContent = f.AlarmContent == "" ? s.PLCAdress : f.AlarmContent,
AlarmType = "停机报警",
AlarmDesc = f.AlarmContent == "" ? s.PLCAdress : f.AlarmContent,
AlarmState = "1",
StartTime = Date,
EndTime = "",//Date
Flag = 0
}).ToList();
}*/
}
private HashSet<string> _allUploadedAlarmContents = new HashSet<string>();
private void DetectNewAlarmsAsync(List<AlarmData> newAlarms)
{
List<AlarmData> tempAlarmList = new List<AlarmData>();
foreach (var alarm in newAlarms)
{
if (!listOld.Any(o => o.PLCAdress == alarm.PLCAdress))
{
listOld.Add(alarm);
tempAlarmList.Add(alarm); //把新报警保存到临时表中
}
}
if (CommonMethods.sysConfig.MesModeSwitching && CommonMethods.mesConfig.isConnected)
{
CommonMethods.hbgMes.UploadEquAlarmAsync(
CommonMethods.mesConfig.DeviceAlarm,
CommonMethods.mesConfig.siteCode,
CommonMethods.mesConfig.lineCode,
CommonMethods.mesConfig.equipNum,
CommonMethods.mesConfig.MaterialCode,
CommonMethods.mesConfig.mesUserName,
tempAlarmList,
strGuidAlarm
);
}
}
/// <summary>
/// 显示报警信息
/// </summary>
private void DisplayAlarmInfo(List<AlarmData> newAlarms)
{
StringBuilder sb = new StringBuilder();
newAlarms.ForEach(r => sb.Append($"{r.AlarmContent} "));
if (sb.Length > 0)
{
CommonMethods.SlideAlarmText = sb.ToString().Substring(0, sb.Length - 10);
}
}
/// <summary>
/// 检测已取消的报警
/// </summary>
private List<AlarmData> DetectCanceledAlarms(List<AlarmData> newAlarms)
{
var canceledAlarms = new List<AlarmData>();
var listOldAlarm = new List<AlarmData>(listOld);
foreach (var item in listOldAlarm)
{
if (!newAlarms.Any(n => n.PLCAdress == item.PLCAdress))
{
item.EndTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
canceledAlarms.Add(item);
listOld.Remove(item);
}
}
return canceledAlarms;
}
/// <summary>
/// 记录已取消的报警信息
/// </summary>
private void LogCanceledAlarms(List<AlarmData> canceledAlarms)
{
var nowDate = DateTime.Now;
string basePath = $@"{CommonMethods.strAlarmLogspath}\{nowDate.Year}\{nowDate.Month}";
string fileName = $@"{nowDate.Day}.csv";
string title = "GUID,报警地址,故障代码,报警内容,开始时间,结束时间,是否停机";
string alarmContent = string.Join("\n", canceledAlarms.Select(m1 =>
$"{m1.AlarmGuid},{m1.PLCAdress},{m1.AlarmCode},{m1.AlarmContent},{m1.StartTime},{m1.EndTime},{m1.AlarmType}"));
CSVHelper<AlarmCSVData>.WriterCSV(basePath, fileName, title, alarmContent);
foreach (var m1 in canceledAlarms)
{
var alarm = new SysLog
{
InsertTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
LogType = "报警日志",
Note = m1.AlarmContent == "" ? m1.PLCAdress : m1.AlarmContent,
AlarmType = "错误",
Operater = CommonMethods.currentAdmin.LoginName,
VarName = m1.PLCAdress,
AlarmSet = "",
AlarmValue = "1",
};
// 显示报警信息
CommonMethods.AddAlarmLog(alarm);//存报警信息
// 报警top10保存
Task.Run(() => { SaveAlarmCount(canceledAlarms); Thread.Sleep(50); });
}
}
/// <summary>
/// 报警结束上传
/// </summary>
/// <param name="canceledAlarms"></param>
/// <param name="strGuidAlarm"></param>
private void UploadCanceledAlarmsAsync(List<AlarmData> canceledAlarms, string strGuidAlarm)
{
//for (int i = 0; i < canceledAlarms.Count; i++)
//{
// var alarm = new List<AlarmData> { canceledAlarms[i] };
if (CommonMethods.sysConfig.MesModeSwitching)
{
CommonMethods.hbgMes.UploadEquAlarmAsync(
CommonMethods.mesConfig.DeviceAlarm,
CommonMethods.mesConfig.siteCode,
CommonMethods.mesConfig.lineCode,
CommonMethods.mesConfig.equipNum,
CommonMethods.mesConfig.MaterialCode,
CommonMethods.mesConfig.mesUserName,
canceledAlarms,
strGuidAlarm
);
}
//}
//_allUploadedAlarmContents.Clear();
}
/// <summary>
/// 报警Top10保存
/// </summary>
private async Task SaveAlarmCount(List<AlarmData> alarmDatas)
{
bool ISAdd = false;
var recordToUpdate = new AlarmCountEntry();
DateTime today = DateTime.Today;
DateTime upTime = DateTime.Now;
var listAlarmStatistics = CommonMethods.db.QueryWhereList<AlarmCountEntry>(it => Convert.ToDateTime(it.AlarmTime.ToString("yyyy-MM-dd")) == today);
List<AlarmCountEntry> fd = new List<AlarmCountEntry>();
if (listAlarmStatistics != null)
{
alarmDatas.ForEach(async r =>
{
recordToUpdate = listAlarmStatistics.FirstOrDefault(x => x.PLCAdress.Trim() == r.PLCAdress);
if (recordToUpdate != null)
{
await CommonMethods.db.UpdateAsync<AlarmCountEntry>(it => it.AlarmCount == it.AlarmCount + 1, it => it.PLCAdress == r.PLCAdress && Convert.ToDateTime(it.AlarmTime.ToString("yyyy-MM-dd")) == today);
}
else
{
ISAdd = true;
AlarmCountEntry alarm = new AlarmCountEntry();
alarm.PLCAdress = r.PLCAdress;
alarm.AlarmContent = r.AlarmContent;
alarm.AlarmCount = 1;
alarm.Class = CommonMethods.strClass;
alarm.AlarmTime = upTime;
fd.Add(alarm);
}
});
if (ISAdd)
{
bool res = await CommonMethods.db.AddReturnBoolAsync(fd);
ISAdd = false;
}
}
// 显示报警信息方法已存数据库,报警TOP10就插入新增了
//else
//{
// foreach (var m in listNew)
// {
// AlarmCountEntry alarm = new AlarmCountEntry();
// alarm.PLCAdress = m.PLCAdress;
// alarm.AlarmContent = m.AlarmContent;
// alarm.AlarmCount = 1;
// alarm.Class = CommonMethods.strClass;
// alarm.AlarmTime = today;
// fd.Add(alarm);
// }
// await CommonMethods.db.AddReturnBoolAsync(fd);
//}
await GetASqlAlarmData(DateTime.Today, CommonMethods.strClass);
}
/// <summary>
/// 读取数据库报警信息
/// </summary>
/// <param name="today"></param>
/// <param name="strClass"></param>
public async Task GetASqlAlarmData(DateTime today, string strClass)
{
try
{
List<ChartDataType> chartAlarms = new List<ChartDataType>();
List<AlarmCountEntry> AlarmDatas = null;
List<string> List_X = new List<string>();
List<int> List_Y = new List<int>();
DateTime baiClassStart = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 8:30:00"));
DateTime baiClassEnd = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 20:29:59"));
DateTime yeClassStart = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 20:30:00"));
DateTime yeClassEnd = Convert.ToDateTime(DateTime.Now.AddDays(1).ToString("yyyy-MM-dd 8:29:59"));
if (strClass == "全天".Translated())
{
AlarmDatas = CommonMethods.db.QueryList<AlarmCountEntry>("AlarmCount", 10, it => Convert.ToDateTime(it.AlarmTime.ToString("yyyy-MM-dd")) == today);
}
else if (strClass == "白班".Translated())
{
AlarmDatas = CommonMethods.db.QueryList<AlarmCountEntry>("AlarmCount", 10, it => it.AlarmTime >= baiClassStart && it.AlarmTime <= baiClassEnd && it.Class == strClass);
}
else
{
AlarmDatas = CommonMethods.db.QueryList<AlarmCountEntry>("AlarmCount", 10, it => it.AlarmTime >= yeClassStart && it.AlarmTime <= yeClassEnd && it.Class == strClass);
}
if (AlarmDatas != null && AlarmDatas.Count > 0)
{
for (int i = 0; i < AlarmDatas.Count; i++)
{
chartAlarms.Add(new ChartDataType()
{
DataType = AlarmDatas[i].AlarmContent,
DataCount = (int)AlarmDatas[i].AlarmCount
});
}
CommonMethods.Lst_AlarmTop10_Qty = chartAlarms;
}
else
{
CommonMethods.Lst_AlarmTop10_Qty = null;
}
}
catch (Exception)
{
}
}
#endregion
#region 下发权限给PLC
/// <summary>
/// 下发权限到PLC
/// </summary>
///
private async Task SendRightToPLCAsync()
{
ushort quanxian = 1;
switch (CommonMethods.currentAdmin.LoginLevel)
{
case "操作员":
quanxian = 1;
break;
case "工程师":
quanxian = 2;
break;
case "管理员":
quanxian = 3;
break;
default:
break;
}
foreach (var plc in CommonMethods.plcDevices)
{
if (plcDeviceMapping.TryGetValue(plc, out var plcDevices))
{
foreach (var plcDevice in plcDevices)
{
if (plcDevice.IsConnected)
{
JYResult result = await Task.Run(() => plc.WriteValue("D21", (short)quanxian, DataType.Short));
if (result.IsSuccess)
{
CommonMethods.AddDataMonitorLog(1, $"Write_PLC_permission_Successful");
}
else
{
CommonMethods.AddDataMonitorLog(2, $"Write_PLC_permission(D15)_Failed");
}
}
}
}
}
}
#endregion
#region 获取白夜班次
bool qiehuan = false;
private void SetClass()
{
try
{
var nowDate = DateTime.Now;
string strClass = "";
DateTime time1 = Convert.ToDateTime($"{nowDate.ToShortDateString()} {CommonMethods.ChangeClassTime}");
DateTime time2 = Convert.ToDateTime($"{nowDate.ToShortDateString()} {Convert.ToDateTime(CommonMethods.ChangeClassTime).AddHours(12).ToString("HH:mm:ss")}");
if (nowDate <= time1 && nowDate >= time2)
{
if (CommonMethods.plcDevices[0].IsConnected)
{
if (!qiehuan)
{
if (!SetPlcTime())
{
CommonMethods.AddLog(true, $"PC写入PLC时间失败".Translated());
}
else
{
qiehuan = true;
CommonMethods.AddLog(false, "PC写入PLC时间成功".Translated());
}
}
}
strClass = "白班".Translated();
}
else
{
qiehuan = false;
strClass = "夜班".Translated();
}
CommonMethods.strClass = strClass;
}
catch (Exception ex)
{
CommonMethods.AddLog(true, "PC写入PLC时间异常".Translated() + ":" + ex.Message);
LogHelper.Instance.WriteEX(ex);
}
}
#endregion
#region 写入PLC时间
/// <summary>
/// 写当前时间给PLC
/// </summary>
private bool SetPlcTime()
{
var nowDate = DateTime.Now;
string yearStr = nowDate.Year.ToString();
bool IsSuccess = false;
// 为防止PLC时间出现偏差,每次自动运行的时候写PLC系统时间
short[] writeArr = new short[]
{
Convert.ToInt16(nowDate.Year),//D70
Convert.ToInt16(nowDate.Month),//D71
Convert.ToInt16(nowDate.Day),//D72
Convert.ToInt16(nowDate.Hour),//D73
Convert.ToInt16(nowDate.Minute),//D74
Convert.ToInt16(nowDate.Second),//D75
(short)1 //D76
};
if (CommonMethods.plcDevices[0].IsConnected)
{
JYResult result = CommonMethods.plcDevices[0].WriteValue("D70", writeArr, DataType.ArrShort);
if (result.IsSuccess)
{
IsSuccess = true;
}
}
return IsSuccess;
}
#region 8、IDisposable 实现
// 如果需要在StopAsync中也显示进度,可以添加一个进度回调
private Task processTask;
public async Task StopAsync(IProgress<string> progress = null)
{
_cts.Cancel();
if (_heartbeatTask != null)
{
progress?.Report("正在停止心跳任务...");
try
{
await _heartbeatTask;
}
catch (OperationCanceledException)
{
// 忽略取消异常
}
}
if (processTask != null)
{
progress?.Report("正在停止处理任务...");
try
{
await processTask;
}
catch (OperationCanceledException)
{
// 忽略取消异常
}
}
foreach (var pair in groupTasks)
{
progress?.Report($"正在停止组任务: {pair.Key}...");
try
{
await pair.Value;
}
catch (OperationCanceledException)
{
// 忽略取消异常
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_cts?.Cancel();
_cts?.Dispose();
processTask?.Wait();
// 断开所有设备连接
foreach (var plc in CommonMethods.plcDevices)
{
plc.Disconnect();
if (plcAlarmReaders.TryGetValue(plc, out var alarmReader))
{
//alarmReader.PLCAlarm_New -= AlrmReader_PLCAlarm_New;
//alarmReader.PLCAlarm_Remove -= AlrmReader_PLCAlarm_Remove;
}
}
CommonMethods.plcDevices.Clear();
plcDeviceMapping.Clear();
plcAlarmReaders.Clear();
CommonMethods.plcStatuses.Clear();
DisconnectAllPlcs();
}
}
#endregion
#endregion
#region 7、辅助方法
private static PLCType GetPLCTypeEnum(string plcTypeString)
{
if (Enum.TryParse(plcTypeString, out PLCType plcType))
{
return plcType;
}
throw new ArgumentException($"PLC 类型无效: {plcTypeString}");
}
#endregion
//#region 8、轴/电机位置监控 X
//private void ReadAxleCSV(int flag, ref List<AxleLog> axleLog, ref List<MotorLog> motorLog)
//{
// axleLog = new List<AxleLog>();
// motorLog = new List<MotorLog>();
// try
// {
// string strLine = "";
// string[] csvReset;//轴位置暂存
// string PlcAddress = string.Empty;
// bool isExits = false;
// switch (flag)
// {
// case 1://本机轴设定位置
// IniConfigHelper.CreateIniFile(configFolderPath, "Motor_YiCiWaiGuanAxle.ini");
// if (!File.Exists(Path.Combine(configFolderPath, "Motor_YiCiWaiGuanAxle.ini")))//判断ini文件是否存在
// {
// isExits = true;
// }
// using (StreamReader reader = new StreamReader(Path.Combine(configFolderPath, "Motor_YiCiWaiGuanAxle.csv"), System.Text.Encoding.GetEncoding("GB2312")))
// {
// while ((strLine = reader.ReadLine()) != null)
// {
// csvReset = strLine.Split(',', '[', ']');
// if (csvReset.Length != 5 && csvReset[0] == "")
// {
// continue;
// }
// if (string.IsNullOrEmpty(csvReset[4]) || string.IsNullOrWhiteSpace(csvReset[4]))
// {
// break; // 空地址跳出读取
// }
// PlcAddress = csvReset[4];
// AxleLog axle = new AxleLog();
// axle.m_AxleDscribe = csvReset[0] + csvReset[1];
// axle.m_AxleLocation = csvReset[3];
// axle.m_AxleAddress = PlcAddress;
// axleLog.Add(axle);
// if (isExits)
// {
// string Value = CommonMethods.plcDevices[0].ReadFloat(PlcAddress).ToString();
// IniConfigHelper.WriteIniData(axle.m_AxleDscribe, axle.m_AxleLocation, Value, Path.Combine(configFolderPath, "Motor_YiCiWaiGuanAxle.ini"));
// }
// }
// reader.Close();
// reader.Dispose();
// }
// break;
// case 2://本机电机位置设定值motor
// IniConfigHelper.CreateIniFile(configFolderPath, "Motor_YiCiWaiGuanMotor.ini");
// if (!File.Exists(Path.Combine(configFolderPath, "Motor_YiCiWaiGuanMotor.ini")))//判断ini文件是否存在
// {
// isExits = true;
// }
// using (StreamReader reader = new StreamReader(Path.Combine(configFolderPath, "Motor_YiCiWaiGuanMotor.csv"), System.Text.Encoding.GetEncoding("GB2312")))
// {
// while ((strLine = reader.ReadLine()) != null)
// {
// csvReset = strLine.Split(',', '[', ']');
// if (csvReset.Length != 5 && csvReset[0] == "")
// {
// continue;
// }
// if (string.IsNullOrEmpty(csvReset[4]) || string.IsNullOrWhiteSpace(csvReset[4]))
// {
// break; // 空地址跳出读取
// }
// PlcAddress = csvReset[4];
// MotorLog motor = new MotorLog();
// motor.m_MotorDscribe = csvReset[0] + csvReset[1];
// motor.m_MotorLocation = csvReset[3];
// motor.m_MotorAddress = PlcAddress;
// motorLog.Add(motor);
// if (isExits)
// {
// string Value = CommonMethods.plcDevices[0].ReadFloat(PlcAddress).ToString();
// IniConfigHelper.WriteIniData(motor.m_MotorDscribe, motor.m_MotorLocation, Value, Path.Combine(configFolderPath, "Motor_YiCiWaiGuanMotor.ini"));
// }
// }
// reader.Close();
// reader.Dispose();
// }
// break;
// default: break;
// }
// }
// catch (Exception ex)
// {
// axleLog = null;
// motorLog = null;
// LogHelper.Instance.WriteError($"轴/电机位置读取配置文件错误:{ex}", "SysErrorLog");
// }
//}
///// <summary>轴/电机对象集合
/////
///// </summary>
//private static List<MotorLog> motorLog = new List<MotorLog>();
//private static List<AxleLog> axleLog = new List<AxleLog>();
//private static Stopwatch swtest = new Stopwatch();
///// <summary>
///// 监控轴位置变化
///// </summary>
//public void ShowAxleEven_Run()
//{
// try
// {
// while (true)
// {
// if (CommonMethods.plcDevices[0] != null && CommonMethods.plcDevices[0].IsConnected)
// {
// short nowPLCstate = CommonMethods.plcDevices[0].ReadInt16("D10");
// if (nowPLCstate != 1)
// {
// if (axleLog.Count < 1)//|| motorLog.Count < 1
// {
// Thread.Sleep(1500);
// ReadAxleCSV(1, ref axleLog, ref motorLog);//轴位置csv文件不存在,out axlelog=null,导致下次判断axlelog.Count报错(未将对象引用设置到对象实例)
// Thread.Sleep(1500);
// }
// else
// {
// try
// {
// // 第二种写法一次读出来
// swtest.Restart();
// JYResult<byte[]> resByte = CommonMethods.plcDevices[0].ReadValue<JYResult<byte[]>>($"{axleLog[0].m_AxleAddress}", DataType.ArrByte, Convert.ToUInt16(axleLog.Count * 4));
// swtest.Stop();
// long tempswt = swtest.ElapsedMilliseconds;
// swtest.Restart();
// if (resByte != null && resByte.IsSuccess && resByte.Content != null)
// {
// string AxleUpLocationOld;
// string AxleUpLocationNew;
// for (int i = 0; i < axleLog.Count; i++)
// {
// double NewCurrent = FloatLib.GetFloatFromByteArray(resByte.Content, i * 4); //D23000 起
// AxleUpLocationOld = IniConfigHelper.ReadIniData(axleLog[i].m_AxleDscribe, axleLog[i].m_AxleLocation, "0", Path.Combine(configFolderPath, "Motor_YiCiWaiGuanAxle.ini"));
// AxleUpLocationNew = Math.Round(NewCurrent, 2).ToString();
// if (AxleUpLocationNew != AxleUpLocationOld)
// {
// string AlterTime = DateTime.Now.ToString("yyyy-MM-dd_HH:mm:ss.fff");
// //日期时间,电机描述,位置描述,位置修改前,当前位置
// LogHelper.PrintMotorLog.LogInfo(AlterTime, axleLog[i].m_AxleDscribe, axleLog[i].m_AxleLocation, AxleUpLocationOld, AxleUpLocationNew);
// IniConfigHelper.WriteIniData(axleLog[i].m_AxleDscribe, axleLog[i].m_AxleLocation, AxleUpLocationNew, Path.Combine(configFolderPath, "Motor_YiCiWaiGuanAxle.ini"));
// }
// }
// }
// swtest.Stop();
// tempswt = swtest.ElapsedMilliseconds;
// }
// catch (Exception ex)
// {
// LogHelper.Instance.WriteError($"轴位置监控线程错误:{ex}", "SysErrorLog");
// }
// }
// }
// }
// else { Thread.Sleep(5000); }
// Thread.Sleep(1000);
// }
// }
// catch (Exception ex)
// {
// LogHelper.Instance.WriteError($"轴位置监控线程错误:{ex}", "SysErrorLog");
// }
//}
///// <summary>
///// 监控电机位置变化 取消
///// </summary>
//public void ShowMotorEven_Run()
//{
// try
// {
// while (true)
// {
// if (CommonMethods.plcDevices[0] != null && CommonMethods.plcDevices[0].IsConnected)
// {
// short nowPLCstate = CommonMethods.plcDevices[0].ReadInt16("D10");
// if (nowPLCstate != 1)
// {
// if (axleLog.Count < 1 || motorLog.Count < 1)
// {
// Thread.Sleep(3000);
// ReadAxleCSV(2, ref axleLog, ref motorLog);//电机位置csv文件不存在,out axlelog=null,导致下次判断axlelog.Count报错(未将对象引用设置到对象实例)
// Thread.Sleep(1500);
// }
// else
// {
// try
// {
// // 第二种写法一次读出来
// swtest.Restart();
// JYResult<byte[]> resByte = CommonMethods.plcDevices[0].ReadValue<JYResult<byte[]>>($"{motorLog[0].m_MotorAddress}", DataType.ArrByte, Convert.ToUInt16(motorLog.Count * 4));
// swtest.Stop();
// long tempswt = swtest.ElapsedMilliseconds;
// swtest.Restart();
// if (resByte != null && resByte.IsSuccess && resByte.Content != null)
// {
// string MotorUpLocationOld;
// string MotorUpLocationNew;
// for (int i = 0; i < motorLog.Count; i++)
// {
// double NewCurrent = FloatLib.GetFloatFromByteArray(resByte.Content, i * 4); //D23000 起
// MotorUpLocationOld = IniConfigHelper.ReadIniData(motorLog[i].m_MotorDscribe, motorLog[i].m_MotorLocation, "0", Path.Combine(configFolderPath, "Motor_YiCiWaiGuanAxle.ini"));
// MotorUpLocationNew = Math.Round(NewCurrent, 2).ToString();
// if (MotorUpLocationNew != MotorUpLocationOld)
// {
// string AlterTime = DateTime.Now.ToString("yyyy-MM-dd_HH:mm:ss.fff");
// //日期时间,电机描述,位置描述,位置修改前,当前位置
// LogHelper.PrintMotorLog.LogInfo(AlterTime, motorLog[i].m_MotorDscribe, motorLog[i].m_MotorLocation, MotorUpLocationOld, MotorUpLocationNew);
// IniConfigHelper.WriteIniData(motorLog[i].m_MotorDscribe, motorLog[i].m_MotorLocation, MotorUpLocationNew, Path.Combine(configFolderPath, "Motor_YiCiWaiGuanAxle.ini"));
// }
// }
// }
// swtest.Stop();
// tempswt = swtest.ElapsedMilliseconds;
// }
// catch (Exception ex)
// {
// LogHelper.Instance.WriteError($"电机位置监控线程错误:{ex}", "SysErrorLog");
// }
// }
// }
// }
// else { Thread.Sleep(5000); }
// Thread.Sleep(1000);
// }
// }
// catch (Exception ex)
// {
// LogHelper.Instance.WriteError($"电机位置监控线程错误:{ex}", "SysErrorLog");
// }
//}
//#endregion
}
}