Files
CapMachine/CapMachine.Wpf/Models/ProModelPars/ProExModel.cs

402 lines
15 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 CapMachine.Wpf.ChannelModel;
using CapMachine.Wpf.Services;
using ImTools;
using Masuit.Tools;
using Masuit.Tools.Hardware;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
using System.Timers;
namespace CapMachine.Wpf.Models.ProModelPars
{
/// <summary>
/// 程序执行模型
/// 包括程序名称和程序步骤集合、程序执行信息
/// 一个参数(速度、排气压力)对应一个程序执行模型
/// </summary>
public class ProExModel : BindableBase
{
/// <summary>
/// 实例化函数
/// </summary>
public ProExModel(Channel<ProRunChannelData> channel)
{
ProRunChannel = channel;
//秒触发一次
CycleTimer = new System.Timers.Timer(1000);
CycleTimer.Elapsed += SlopExCycleAction;
CycleTimer.AutoReset = true;
CycleTimer.Enabled = true;
CycleTimer.Start();
}
/// <summary>
/// 程序执行管道
/// </summary>
public Channel<ProRunChannelData> ProRunChannel { get; set; }
/// <summary>
/// 名称
/// </summary>
public string MeterName { get; set; }
/// <summary>
/// 当前模型是否启用
/// 当前有很多参数都是预设,但是有些参数是为其他的项目准备的,可能在当前的项目上都不会配置和使用。
/// 故设置Enable属性
/// </summary>
public bool Enable { get; set; } = true;
/// <summary>
/// 程序步骤集合
/// </summary>
public List<ProStepExe> ListProStepExe { get; set; }
/// <summary>
/// 仪表步骤执行时间信息
/// </summary>
public ProRunTime ProRunTimeModel { get; set; }
/// <summary>
/// 下一步步骤数据执行
/// </summary>
public ProStepExe NextProStepExe { get; set; }
/// <summary>
/// 当前步骤数据执行
/// 给看步骤是否变化使用
/// </summary>
public ProStepExe CurProStepExe { get; set; }
/// <summary>
/// 上一步步骤数据执行
/// 给看步骤是否变化使用
/// </summary>
public ProStepExe LastProStepExe { get; set; }
/// <summary>
/// 当前程序段时间长
/// </summary>
public int CurProTimeSum { get; set; }
/// <summary>
/// 当前程序段开始时间
/// </summary>
public DateTime CurProStartTime { set; get; }
#region
public EventHandler<string> RunTimeCallSglEvent;
/// <summary>
/// 是否启用
/// </summary>
public bool RunEnable { get; set; } = false;
/// <summary>
/// RunTimeCallSglEvent 是否注册关联方法
/// </summary>
public bool EventRegister { get; set; } = false;
/// <summary>
/// 当前步骤开始运行时间
/// </summary>
public DateTime StepStartDt { get; set; }
/// <summary>
/// 当前步骤结束运行时间
/// </summary>
public DateTime StepEndDt { get; set; }
private DateTime _CurrentDateTime;
/// <summary>
/// 当前时间
/// </summary>
public DateTime CurrentDateTime
{
get
{
return _CurrentDateTime;
}
set
{
//value.ToString("yyyy-MM-dd HH:mm:ss") == EndDateTime.ToString("yyyy-MM-dd HH:mm:ss")
if (RunEnable == true && value >= StepEndDt)
{
_CurrentDateTime = value;
//达到后不再触发
//RunEnable = false;
//时间到了触发下载下一步步骤
//不为空的数据
if (NextProStepExe == null)
{
Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{MeterName} " +
$"【Msg】没有下一步当前仪表参数全部执行完毕 ");
//为空时不执行后续的数据
RunEnable = false;
return;
}
Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{MeterName} " +
$"【程序Seg】{CurProStepExe.ProSegName} " +
$"【程序步骤】{CurProStepExe.MeterStep} " +
$"【Msg】时间到开始执行下一步步骤 ");
////////首先判断参数是否相同///////////
var SvResult = false;//True代表不同false代表相同
//判断PID是否跟上一次一样
if (CurProStepExe.EndSV != NextProStepExe.EndSV)
{
SvResult = true;
}
var PidResult = false;//True代表不同false代表相同
//判断PID是否跟上一次一样
if (CurProStepExe.PIDNo != NextProStepExe.PIDNo)
{
PidResult = true;
}
var LimitResult = false;//True代表不同false代表相同
//判断Limit是否跟上一次一样
if (CurProStepExe.LimitNo != NextProStepExe.LimitNo)
{
LimitResult = true;
}
////////发送步骤信息///////////
if (NextProStepExe.ExistSlop)
{
//存在坡度数据
var SecStepDur = NextProStepExe.EndSV - NextProStepExe.StartSV;
var SecStepValue = SecStepDur * 1.0 / NextProStepExe.KeepTime;
//先清除数据
ListSlopExStep.Clear();
//组装斜坡数据,按照秒为间隔发送
for (var i = 1; i <= NextProStepExe.KeepTime; i++)
{
var SlopExStep = new SlopExStep()
{
StepNo = i,
SV = NextProStepExe.StartSV + (int)(SecStepValue * i),
IsHasEx = false,
};
ListSlopExStep.Add(SlopExStep);
}
//需要发送一次StartSV数据吗
//组装完成开始循环打点
StartSlopExStep();
}
else//不存在斜坡数据的话则直接发送EndSV数据即可
{
ProRunChannel.Writer.TryWrite(new ProRunChannelData()
{
MeterName = MeterName,
SV = NextProStepExe.EndSV,
ProSegName = NextProStepExe.ProSegName,
MeterStep = NextProStepExe.MeterStep,
CurLoadLimit = LimitResult == true ? new Limit() { Up = (short)NextProStepExe.CurConfigLimitDto.Up, Down = (short)NextProStepExe.CurConfigLimitDto.Down } : new Limit(),
CurLoadPID = PidResult == true ? new PID() { P = (short)NextProStepExe.CurConfigPIDDto.P, I = (short)NextProStepExe.CurConfigPIDDto.I, D = (short)NextProStepExe.CurConfigPIDDto.D } : new PID(),
RunStepType = GetRunStepType(PidResult, LimitResult, true),
});
}
////////准备新的数据///////////
LastProStepExe = CurProStepExe.DeepClone();
//准备下一步步骤数据
CurProStepExe = NextProStepExe.DeepClone();
//标记状态-当前执行中
if (ListProStepExe.Where(a => a.MeterStep == CurProStepExe.MeterStep).Any())
{
ListProStepExe.FindFirst(a => a.MeterStep == CurProStepExe.MeterStep).MeterStepIsExeing = true;
}
//标记状态-上一个执行完毕标记
if (ListProStepExe.Where(a => a.MeterStep == LastProStepExe.MeterStep).Any())
{
ListProStepExe.FindFirst(a => a.MeterStep == LastProStepExe.MeterStep).MeterStepIsExeing = false;
}
//标记状态-上一个执行完成
if (ListProStepExe.Where(a => a.MeterStep == LastProStepExe.MeterStep).Any())
{
ListProStepExe.FindFirst(a => a.MeterStep == LastProStepExe.MeterStep).MeterStepIsOK = true;
}
//设置下一步步骤数据
if (ListProStepExe.Where(x => x.MeterStep == CurProStepExe.MeterStep + 1).Any())
{
//存在下一步数据
NextProStepExe = ListProStepExe.FirstOrDefault(x => x.MeterStep == CurProStepExe.MeterStep + 1);
}
else
{
//没有下一步数据则判定为最后一步
NextProStepExe = null;
}
//设置步骤开始时间
StepStartDt = DateTime.Now;
//设置步骤结束时间
StepEndDt = StepStartDt.AddSeconds(CurProStepExe.KeepTime);
//设置下一步步骤运行时间
RunEnable = true;
}
else
{
_CurrentDateTime = value;
RunTime = (int)(_CurrentDateTime - StepEndDt).TotalSeconds;
}
}
}
/// <summary>
/// 当前步骤已经运行时长-秒
/// </summary>
public int RunTime { get; set; }
/// <summary>
/// 通过组合Pid和Limit组合出运行步骤类型
/// </summary>
/// <param name="pid">PID是否不同</param>
/// <param name="limit">Limit是否不同</param>
/// <param name="sv">SV是否不同</param>
/// <returns>运行步骤类型</returns>
private RunStepType GetRunStepType(bool pid, bool limit, bool sv)
{
if (pid && limit && sv)
{
return RunStepType.Step;
}
else if (pid && sv)
{
return RunStepType.StepPID;
}
else if (limit && sv)
{
return RunStepType.StepLimit;
}
else if (sv)
{
return RunStepType.StepSV;
}
else
{
return RunStepType.Step;
}
}
#endregion
#region
/// <summary>
/// 开始打点执行
/// </summary>
private void StartSlopExStep()
{
SlopExEnable = true;
}
/// <summary>
/// 斜率执行步骤集合
/// 打点集合
/// </summary>
public List<SlopExStep> ListSlopExStep { get; set; } = new List<SlopExStep>();
/// <summary>
/// 斜率执行循环周期
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <exception cref="NotImplementedException"></exception>
private void SlopExCycleAction(object? sender, ElapsedEventArgs e)
{
try
{
//如果Execute执行的是一个很耗时的方法会导致方法未执行完毕定时器又启动了一个线程来执行Execute方法
//CycleTimer.Stop(); //先关闭定时器
if (SlopExEnable)
{
var NoExData = ListSlopExStep.Where(a => a.IsHasEx == false).OrderBy(a => a.StepNo).ToList();
if (NoExData.Any())
{
//发送步骤信息
ProRunChannel.Writer.TryWrite(new ProRunChannelData()
{
MeterName = MeterName,
SV = NoExData.First().SV,
ProSegName = CurProStepExe.ProSegName,
MeterStep = CurProStepExe.MeterStep,
SlopStepNo = NoExData.First().StepNo,
CurLoadLimit = null,
CurLoadPID = null,
RunStepType = RunStepType.SlopCell,
});
//发送完毕后进行标记数据
NoExData.First().IsHasEx = true;
Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{MeterName} " +
$"【程序Seg】{CurProStepExe.ProSegName} " +
$"【程序步骤】{CurProStepExe.MeterStep} " +
$"【斜坡打点步骤】{NoExData.First().StepNo} " +
$"【斜坡打点值SV】{NoExData.First().SV} " +
$"【Msg】发送斜坡打点 ");
}
else
{
//执行完毕了,没有要执行的数据效率
SlopExEnable = false;
Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{MeterName} " +
$"【程序Seg】{CurProStepExe.ProSegName} " +
$"【程序步骤】{CurProStepExe.MeterStep} " +
$"【Msg】斜坡打点执行完毕 ");
return;
}
}
//CycleTimer.Start(); //执行完毕后再开启器
}
catch (Exception ex)
{
//CycleTimer.Start(); //执行完毕后再开启器
//LogService.Info($"时间:{DateTime.Now.ToString()}-【PwAnalyze-CycleAction】-{ex.Message}");
}
}
/// <summary>
/// 周期定时器
/// </summary>
private System.Timers.Timer CycleTimer { get; set; }
/// <summary>
/// 步骤斜率执行使能状态
/// </summary>
public bool SlopExEnable { get; set; } = false;
#endregion
}
}