配置参数下载和解析的开发-未完成

This commit is contained in:
2025-02-24 11:21:23 +08:00
parent c22a8cc98f
commit d2ef6f9961
25 changed files with 2273 additions and 189 deletions

View File

@@ -8,4 +8,7 @@
<ItemGroup>
<PackageReference Include="FreeSql" Version="3.5.102" />
</ItemGroup>
<ItemGroup>
<Folder Include="ProExecuteModel\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,38 @@
using FreeSql.DataAnnotations;
namespace CapMachine.Model
{
/// <summary>
/// 报警配置
/// </summary>
[Table(Name = "ConfigAlarm")]
public class ConfigAlarm
{
/// <summary>
/// 主键
/// </summary>
[Column(IsPrimary = true, IsIdentity = true)]
public long Id { get; set; }
/// <summary>
/// 序号
/// </summary>
[Column(Name = "IndexNo", IsNullable = false)]
public int IndexNo { get; set; }
/// <summary>
/// 快速设置仪表名称
/// </summary>
[Column(Name = "MeterName", IsNullable = true, StringLength = 30)]
public string MeterName { get; set; }
/// <summary>
/// Alarm
/// </summary>
[Column(Name = "Alarm", IsNullable = true)]
public double Alarm { get; set; }
[Column(ServerTime = DateTimeKind.Local, CanUpdate = false)]
public DateTime CreateTime { get; set; }
}
}

View File

@@ -7,159 +7,159 @@ using System.Threading.Tasks;
namespace CapMachine.Model
{
/// <summary>
/// 程序段具体步骤执行信息
/// </summary>
[Table(Name = "ProStepExecute")]
public class ProStepExecute
{
/// <summary>
/// 主键
/// </summary>
[Column(IsPrimary = true)]
public Guid Id { get; set; }
///// <summary>
///// 程序段具体步骤执行信息
///// </summary>
//[Table(Name = "ProStepExecute")]
//public class ProStepExecute
//{
// /// <summary>
// /// 主键
// /// </summary>
// [Column(IsPrimary = true)]
// public Guid Id { get; set; }
/// <summary>
/// 程序段名称
/// </summary>
[Column(Name = "ProName", IsNullable = false, StringLength = 20)]
public string ProName { get; set; }
// /// <summary>
// /// 程序段名称
// /// </summary>
// [Column(Name = "ProName", IsNullable = false, StringLength = 20)]
// public string ProName { get; set; }
/// <summary>
/// 程序段步骤
/// </summary>
[Column(Name = "ProStep", IsNullable = false)]
public int ProStep { get; set; }
// /// <summary>
// /// 程序段步骤
// /// </summary>
// [Column(Name = "ProStep", IsNullable = false)]
// public int ProStep { get; set; }
/// <summary>
/// 程序段反复
/// </summary>
[Column(Name = "ProRepeat")]
public int ProRepeat { get; set; }
// /// <summary>
// /// 程序段反复
// /// </summary>
// [Column(Name = "ProRepeat")]
// public int ProRepeat { get; set; }
/// <summary>
/// 是否正在执行当前程序段
/// </summary>
[Column(Name = "IsCurrentProStep")]
public bool IsCurrentProStep { get; set; }
// /// <summary>
// /// 是否正在执行当前程序段
// /// </summary>
// [Column(Name = "IsCurrentProStep")]
// public bool IsCurrentProStep { get; set; }
/////////////////////////////////////////////////////////////////
////////////////////////程序步骤///////////////////////////////
////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////
// ////////////////////////程序步骤///////////////////////////////
// ////////////////////////////////////////////////////////////////
/// <summary>
/// 是否正在执行当前程序段
/// </summary>
[Column(Name = "IsCurrentMeterStep")]
public bool IsCurrentMeterStep { get; set; }
// /// <summary>
// /// 是否正在执行当前程序段
// /// </summary>
// [Column(Name = "IsCurrentMeterStep")]
// public bool IsCurrentMeterStep { get; set; }
/// <summary>
/// 仪表功能名称
/// </summary>
[Column(Name = "MeterName", IsNullable = false, StringLength = 20)]
public string MeterName { get; set; }
// /// <summary>
// /// 仪表功能名称
// /// </summary>
// [Column(Name = "MeterName", IsNullable = false, StringLength = 20)]
// public string MeterName { get; set; }
/// <summary>
/// 步骤
/// </summary>
[Column(Name = "MeterStep", IsNullable = false)]
public int MeterStep { get; set; }
// /// <summary>
// /// 步骤
// /// </summary>
// [Column(Name = "MeterStep", IsNullable = false)]
// public int MeterStep { get; set; }
/// <summary>
/// 速度 DegC
/// </summary>
[Column(Name = "SV", IsNullable = true)]
public int SV { get; set; }
// /// <summary>
// /// 速度 DegC
// /// </summary>
// [Column(Name = "SV", IsNullable = true)]
// public int SV { get; set; }
/// <summary>
/// 时间-分钟
/// </summary>
[Column(Name = "TimeMin", IsNullable = true)]
public int TimeMin { get; set; }
// /// <summary>
// /// 时间-分钟
// /// </summary>
// [Column(Name = "TimeMin", IsNullable = true)]
// public int TimeMin { get; set; }
/// <summary>
/// 时间-秒
/// </summary>
[Column(Name = "TimeSec", IsNullable = true)]
public int TimeSec { get; set; }
// /// <summary>
// /// 时间-秒
// /// </summary>
// [Column(Name = "TimeSec", IsNullable = true)]
// public int TimeSec { get; set; }
/// <summary>
/// PID NO
/// </summary>
[Column(Name = "PIDNo", IsNullable = true)]
public int PIDNo { get; set; }
// /// <summary>
// /// PID NO
// /// </summary>
// [Column(Name = "PIDNo", IsNullable = true)]
// public int PIDNo { get; set; }
/// <summary>
/// Limit NO
/// </summary>
[Column(Name = "LitmitNo", IsNullable = true)]
public int LitmitNo { get; set; }
// /// <summary>
// /// Limit NO
// /// </summary>
// [Column(Name = "LitmitNo", IsNullable = true)]
// public int LitmitNo { get; set; }
/// <summary>
/// Alarm NO
/// </summary>
[Column(Name = "AlarmNo", IsNullable = true)]
public int AlarmNo { get; set; }
// /// <summary>
// /// Alarm NO
// /// </summary>
// [Column(Name = "AlarmNo", IsNullable = true)]
// public int AlarmNo { get; set; }
///// <summary>
///// 时间信号
///// </summary>
//[Column(Name = "TimeSign1", IsNullable = true)]
//public int TimeSign1 { get; set; }
// ///// <summary>
// ///// 时间信号
// ///// </summary>
// //[Column(Name = "TimeSign1", IsNullable = true)]
// //public int TimeSign1 { get; set; }
///// <summary>
///// 时间信号
///// </summary>
//[Column(Name = "TimeSign2", IsNullable = true)]
//public int TimeSign2 { get; set; }
// ///// <summary>
// ///// 时间信号
// ///// </summary>
// //[Column(Name = "TimeSign2", IsNullable = true)]
// //public int TimeSign2 { get; set; }
///// <summary>
///// 时间信号
///// </summary>
//[Column(Name = "TimeSign3", IsNullable = true)]
//public int TimeSign3 { get; set; }
// ///// <summary>
// ///// 时间信号
// ///// </summary>
// //[Column(Name = "TimeSign3", IsNullable = true)]
// //public int TimeSign3 { get; set; }
/// <summary>
/// 步进重复
/// </summary>
[Column(Name = "Repeat", IsNullable = true)]
public int StepRepeat { get; set; }
// /// <summary>
// /// 步进重复
// /// </summary>
// [Column(Name = "Repeat", IsNullable = true)]
// public int StepRepeat { get; set; }
///// <summary>
///// 拓展字段1
///// </summary>
//[Column(Name = "FeildExte1", IsNullable = true)]
//public string FeildExte1 { get; set; }
// ///// <summary>
// ///// 拓展字段1
// ///// </summary>
// //[Column(Name = "FeildExte1", IsNullable = true)]
// //public string FeildExte1 { get; set; }
///// <summary>
///// 拓展字段1
///// </summary>
//[Column(Name = "FeildExte2", IsNullable = true)]
//public string FeildExte2 { get; set; }
// ///// <summary>
// ///// 拓展字段1
// ///// </summary>
// //[Column(Name = "FeildExte2", IsNullable = true)]
// //public string FeildExte2 { get; set; }
///// <summary>
///// 拓展字段1
///// </summary>
//[Column(Name = "FeildExte3", IsNullable = true)]
//public string FeildExte3 { get; set; }
// ///// <summary>
// ///// 拓展字段1
// ///// </summary>
// //[Column(Name = "FeildExte3", IsNullable = true)]
// //public string FeildExte3 { get; set; }
///// <summary>
///// 拓展字段1
///// </summary>
//[Column(Name = "FeildExte4", IsNullable = true)]
//public string FeildExte4 { get; set; }
// ///// <summary>
// ///// 拓展字段1
// ///// </summary>
// //[Column(Name = "FeildExte4", IsNullable = true)]
// //public string FeildExte4 { get; set; }
///// <summary>
///// 拓展字段1
///// </summary>
//[Column(Name = "FeildExte5", IsNullable = true)]
//public string FeildExte5 { get; set; }
// ///// <summary>
// ///// 拓展字段1
// ///// </summary>
// //[Column(Name = "FeildExte5", IsNullable = true)]
// //public string FeildExte5 { get; set; }
[Column(ServerTime = DateTimeKind.Local, CanUpdate = false)]
public DateTime CreateTime { get; set; }
// [Column(ServerTime = DateTimeKind.Local, CanUpdate = false)]
// public DateTime CreateTime { get; set; }
}
//}
}

View File

@@ -92,13 +92,16 @@ namespace CapMachine.Wpf
{
////注册日志服务
containerRegistry.RegisterSingleton<ILogService, LogService>();
//注册AutoMapper 将IAutoMapperProvider注入IOC容器并对外提供IMapper注入类型。
containerRegistry.RegisterSingleton<IMapperProvider, MapperConfig>();
containerRegistry.Register(typeof(IMapper), GetMapper);
//注册基础的服务
//containerRegistry.RegisterSingleton<IHostDialogService, DialogHostService>();
//containerRegistry.RegisterSingleton<IAppStartService, AppStartService>();
//containerRegistry.RegisterSingleton<IApplicationContext, ApplicationContext>();
containerRegistry.RegisterSingleton<ConfigService>();
containerRegistry.RegisterSingleton<AlarmService>();
////注册设备服务
@@ -112,10 +115,8 @@ namespace CapMachine.Wpf
containerRegistry.RegisterSingleton<SysRunService>();
containerRegistry.RegisterSingleton<ComActionService>();
//注册AutoMapper 将IAutoMapperProvider注入IOC容器并对外提供IMapper注入类型。
containerRegistry.RegisterSingleton<IMapperProvider, MapperConfig>();
containerRegistry.Register(typeof(IMapper), GetMapper);
containerRegistry.RegisterSingleton<ProRuntimeService>();
string strsqllite = System.AppDomain.CurrentDomain.BaseDirectory + @"Db\CapMachine.db";
string strslocaldb = System.AppDomain.CurrentDomain.BaseDirectory + @"Db\CapMachineDb";
@@ -256,6 +257,7 @@ namespace CapMachine.Wpf
var appVersionService10 = ContainerLocator.Container.Resolve<HighSpeedDataService>();
//var appVersionService11 = ContainerLocator.Container.Resolve<PPCService>();
var appVersionService15 = ContainerLocator.Container.Resolve<ComActionService>();
var appVersionService16 = ContainerLocator.Container.Resolve<ProRuntimeService>();

View File

@@ -715,8 +715,6 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Folder Include="Models\ProModelPars\" />
<Folder Include="Tool\" />
<Folder Include="LocalDll\" />
</ItemGroup>
<ItemGroup>

View File

@@ -0,0 +1,57 @@
using CapMachine.Wpf.Dtos;
using CapMachine.Wpf.Models.ProModelPars;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.ChannelModel
{
/// <summary>
/// 程序运行管道数据
/// </summary>
public class ProRunChannelData
{
/// <summary>
/// 参数名称
/// </summary>
public string? MeterName { get; set; }
/// <summary>
/// 程序Seg
/// </summary>
public string? ProSegName { get; set; }
/// <summary>
/// 程序步骤
/// </summary>
public int MeterStep { get; set; }
/// <summary>
/// 斜坡打点步骤
/// </summary>
public int SlopStepNo { get; set; }
/// <summary>
/// 值类型
/// </summary>
public RunStepType RunStepType { get; set; }
/// <summary>
/// 值
/// </summary>
public int? SV { get; set; }
/// <summary>
/// PID的配置信息
/// </summary>
public PID? CurLoadPID { get; set; }
/// <summary>
/// Alarm的配置信息
/// </summary>
public Limit? CurLoadLimit { get; set; }
}
}

View File

@@ -0,0 +1,43 @@
using Prism.Mvvm;
namespace CapMachine.Wpf.Dtos
{
public class ConfigAlarmDto : BindableBase
{
/// <summary>
/// 主键
/// </summary>
public long Id { get; set; }
private string? _MeterName;
/// <summary>
/// 仪表名称
/// </summary>
public string? MeterName
{
get { return _MeterName; }
set { _MeterName = value; RaisePropertyChanged(); }
}
private int _IndexNo;
/// <summary>
/// 序号
/// </summary>
public int IndexNo
{
get { return _IndexNo; }
set { _IndexNo = value; RaisePropertyChanged(); }
}
private double _Alarm;
/// <summary>
/// Alarm
/// </summary>
public double Alarm
{
get { return _Alarm; }
set { _Alarm = value; RaisePropertyChanged(); }
}
}
}

View File

@@ -1,4 +1,5 @@
using CapMachine.Model;
using CapMachine.Wpf.Models.ProModelPars;
using HslCommunication;
using Prism.Mvvm;
@@ -17,12 +18,12 @@ namespace CapMachine.Wpf.Models
/// </summary>
public MeterRtDataModel()
{
ListProStepExecuteInfo = new List<ProStepExecute>();
ListProStepExecuteInfo = new List<ProStepExe>();
ListQuickProStepExecuteInfo = new List<QuickProStepExecute>();
QuickRunTimeInfo = new QuickRunTime();
QuickNextMeterStep = new QuickProStepExecute();
RunTimeInfo = new MeterRunTime();
NextMeterStep = new ProStepExecute();
NextMeterStep = new ProStepExe();
}
@@ -252,7 +253,7 @@ namespace CapMachine.Wpf.Models
/// <summary>
/// 程序段和程序步骤执行具体方法
/// </summary>
public List<ProStepExecute> ListProStepExecuteInfo { get; set; }
public List<ProStepExe> ListProStepExecuteInfo { get; set; }
/// <summary>
/// 快速设置程序段和程序步骤执行具体方法
@@ -277,7 +278,7 @@ namespace CapMachine.Wpf.Models
/// <summary>
/// 仪表下一步具体程序步骤
/// </summary>
public ProStepExecute NextMeterStep { get; set; }
public ProStepExe NextMeterStep { get; set; }
/// <summary>
/// Quick仪表下一步具体程序步骤

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Models
{
/// <summary>
/// PLC加载配置单元
/// 下载PLC数据用整型的数据下载但是我们这边可能是浮点数需要格式的转换精度的转换
/// </summary>
public class PlcLoadConfigCell
{
/// <summary>
/// 配置字段 名称
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 地址
/// </summary>
public string? Address { get; set; }
/// <summary>
/// 精度 1,10,100,1000
/// </summary>
public int Precision { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Models.ProModelPars
{
public class Alarm
{
public double AlarmValue { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Models.ProModelPars
{
/// <summary>
/// 下载时用的Limit
/// 进制和精度也需要处理好
/// </summary>
public class Limit
{
/// <summary>
/// Limit-Up
/// </summary>
public short Up { get; set; }
/// <summary>
/// Limit-Down
/// </summary>
public short Down { get; set; }
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Models.ProModelPars
{
/// <summary>
/// 下载时用的PID
/// 进制也需要处理好
/// </summary>
public class PID
{
/// <summary>
/// PID-P
/// </summary>
public short P { get; set; }
/// <summary>
/// PID-I
/// </summary>
public short I { get; set; }
/// <summary>
/// PID-D
/// </summary>
public short D { get; set; }
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Models.ProModelPars
{
/// <summary>
/// 配置限制Dto
/// </summary>
public class ParsConfigLimitDto
{
/// <summary>
/// 主键
/// </summary>
public long Id { get; set; }
/// <summary>
/// 设置仪表名称
/// </summary>
public string? MeterName { get; set; }
/// <summary>
/// 序号
/// </summary>
public int IndexNo { get; set; }
/// <summary>
/// 上限
/// </summary>
public decimal Up { get; set; }
/// <summary>
/// 下限
/// </summary>
public decimal Down { get; set; }
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Models.ProModelPars
{
/// <summary>
/// PID 配置模型Dto
/// </summary>
public class ParsConfigPIDDto
{
/// <summary>
/// 主键
/// </summary>
public long Id { get; set; }
/// <summary>
/// 设置仪表名称
/// </summary>
public string? MeterName { get; set; }
/// <summary>
/// 序号
/// </summary>
public int IndexNo { get; set; }
/// <summary>
/// P
/// </summary>
public decimal P { get; set; }
/// <summary>
/// I
/// </summary>
public int I { get; set; }
/// <summary>
/// D
/// </summary>
public int D { get; set; }
}
}

View File

@@ -0,0 +1,401 @@
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
}
}

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Models.ProModelPars
{
/// <summary>
/// 程序运行时间
/// </summary>
public class ProRunTime
{
public EventHandler<string> RunTimeCallSglEvent;
/// <summary>
/// 是否启用
/// </summary>
public bool RunEnable { get; set; } = false;
/// <summary>
/// RunTimeCallSglEvent 是否注册关联方法
/// </summary>
public bool EventRegister { get; set; } = false;
/// <summary>
/// 当前仪表名称
/// </summary>
public string MeterName { get; set; }
/// <summary>
/// 当前程序段名称
/// </summary>
public string ProName { get; set; }
/// <summary>
/// 当前仪表程序步骤
/// </summary>
public int MeterStep { get; set; }
/// <summary>
/// 当前步骤开始运行时间
/// </summary>
public DateTime StartDateTime { get; set; }
/// <summary>
/// 当前步骤结束运行时间
/// </summary>
public DateTime EndDateTime { 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 >= EndDateTime)
{
currentDateTime = value;
RunEnable = false;
//时间到了触发下载新的步骤
//RunTimeCallSglEvent(ProName, MeterName, MeterStep);
//RunTimeCallSglEvent.BeginInvoke(ProName, MeterName, MeterStep, null, null);
//RunEnable = false;
}
else
{
currentDateTime = value;
RunTime = (int)(currentDateTime - StartDateTime).TotalSeconds;
}
}
}
/// <summary>
/// 当前步骤已经运行时长-秒
/// </summary>
public int RunTime { get; set; }
}
}

View File

@@ -0,0 +1,135 @@
using CapMachine.Model;
using CapMachine.Wpf.Dtos;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Models.ProModelPars
{
/// <summary>
/// 程序分解后的执行步骤
/// </summary>
public class ProStepExe : BindableBase
{
/// <summary>
/// 程序段名称
/// </summary>
public string? ProSegName { get; set; }
/// <summary>
/// 程序段步骤
/// </summary>
public int ProSegStep { get; set; }
/// <summary>
/// 程序段重复执行次数
/// </summary>
public int ProSegRepeat { get; set; }
/// <summary>
/// 程序段当前是否执行中
/// </summary>
public bool ProSegIsExeing { get; set; }
/////////////////////////////////////////////////////////////////
////////////////////////程序步骤///////////////////////////////
////////////////////////////////////////////////////////////////
///// <summary>
///// 程序步骤标记
///// </summary>
//public StepPosMark StepPosMark { get; set; }
/// <summary>
/// 仪表参数当前是否执行中
/// </summary>
public bool MeterStepIsExeing { get; set; }
/// <summary>
/// 仪表参数是否执行完成
/// </summary>
public bool MeterStepIsOK { get; set; }
/// <summary>
/// 仪表参数名称
/// </summary>
public string? MeterName { get; set; }
/// <summary>
/// 仪表参数步骤
/// </summary>
public int MeterStep { get; set; }
/// <summary>
/// 这个步骤是打开具体设置步骤界面的那个层面的信息例如2-3,代表是程序2里面的仪表步骤3方便调试和给液击使用
/// </summary>
public string? ProStepInfo { get; set; }
///// <summary>
///// 启用状态-没有启用就是什么数据都没有
///// Const-常值-常值StepValue有值只有一个步骤CycleTime为0
///// MultisStep-有步骤细节-此时在一个仪表下就会有很多步骤的细节数据
///// </summary>
//public ConfigValueType ConfigState { get; set; }
/// <summary>
/// StartSV- 步骤的开始SV
/// 最终的写到PLC结果值经过进制转换
/// </summary>
public int StartSV { get; set; }
/// <summary>
/// EndSV- 步骤的目标SV
/// 最终的写到PLC结果值经过进制转换
/// </summary>
public int EndSV { get; set; }
/// <summary>
/// KeepTime Sec
/// </summary>
public int KeepTime { get; set; }
/// <summary>
/// 是否启用坡度
/// 存在斜坡容易判断,非斜坡是常值
/// 常值有两种情况:
/// 一个是设置时就直接设定为常值,
/// 另一个是斜率步骤里面比如起始8000结束9000那么也是常值,因为当前模型是拆分详细之后的,他可以判断详细步骤的斜坡信息
/// </summary>
public bool ExistSlop { get; set; }
///// <summary>
///// 时间-秒-斜坡时间
///// </summary>
//public int SlopTimeSec { get; set; }
/// <summary>
/// PIDNo
/// </summary>
public int PIDNo { get; set; }
/// <summary>
/// PID的配置信息
/// </summary>
public ConfigPIDDto? CurConfigPIDDto { get; set; }
/// <summary>
/// LimitNo
/// </summary>
public int LimitNo { get; set; }
/// <summary>
/// AlarmNo的配置信息
/// </summary>
public ConfigLimitDto? CurConfigLimitDto { get; set; }
/// <summary>
/// AlarmNo
/// </summary>
public int AlarmNo { get; set; }
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Models.ProModelPars
{
/// <summary>
/// 运行和下载的数据类型
/// </summary>
public enum RunStepType
{
/// <summary>
/// 正常的步骤信息 SV-PID-Limit 下载数据
/// 就是包括SV PID和SLIMIT的数据当然SV PID和SLIMIT跟上次是一样的话则不需要下载
/// </summary>
Step = 1,
/// <summary>
/// 正常的步骤信息-SV-PID 下载数据
/// 就是包括SV PID和SLIMIT的数据当然SV PID和SLIMIT跟上次是一样的话则不需要下载
/// </summary>
StepPID = 2,
/// <summary>
/// 正常的步骤信息-SV-Limit 下载数据
/// 就是包括SV PID和SLIMIT的数据当然SV PID和SLIMIT跟上次是一样的话则不需要下载
/// </summary>
StepLimit = 3,
/// <summary>
/// 正常的步骤信息-SV 下载数据
/// 就是包括SV PID和SLIMIT的数据当然SV PID和SLIMIT跟上次是一样的话则不需要下载
/// </summary>
StepSV = 4,
/// <summary>
/// 斜率单元
/// 带斜率的数据打点执行只传送SV值
/// 比如速度0-5000 5秒此时执行第一秒1000第二秒2000第三秒3000第四秒4000第五秒5000
/// </summary>
SlopCell = 10
}
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Models.ProModelPars
{
/// <summary>
/// 斜率执行步骤
/// </summary>
public class SlopExStep
{
/// <summary>
/// 步骤号
/// </summary>
public int StepNo { get; set; }
/// <summary>
/// SV值
/// </summary>
public int SV { get; set; }
/// <summary>
/// 是否已经执行
/// </summary>
public bool IsHasEx { get; set; }=false;
}
}

View File

@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Models.ProModelPars
{
/// <summary>
/// PLC下载单元
/// </summary>
public class StepPlcCell : HslCommunication.IDataTransfer
{
public ushort ReadCount { get; set; } = 10;
public void ParseSource(byte[] Content)
{
throw new NotImplementedException();
}
public byte[] ToSource()
{
throw new NotImplementedException();
}
#region
/// <summary>
/// 时间-分钟
/// </summary>
public short TimeMin { get; set; }
/// <summary>
/// 时间-秒
/// </summary>
public short TimeSec { get; set; }
/// <summary>
/// SV值
/// </summary>
public short SV { get; set; }
/// <summary>
/// PID-P
/// </summary>
public short PID_P { get; set; }
/// <summary>
/// PID-I
/// </summary>
public short PID_I { get; set; }
/// <summary>
/// PID-D
/// </summary>
public short PID_D { get; set; }
/// <summary>
/// Limit-Up
/// </summary>
public short Limit_Up { get; set; }
/// <summary>
/// Limit-Down
/// </summary>
public short Limit_Down { get; set; }
#endregion
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Models.ProModelPars
{
/// <summary>
/// 程序步骤标记
/// </summary>
public enum StepPosMark
{
}
}

View File

@@ -5,6 +5,7 @@ using CapMachine.Wpf.Models;
using CapMachine.Wpf.Models.Tag;
using CapMachine.Wpf.PrismEvent;
using HslCommunication;
using HslCommunication.Profinet.Melsec;
using HslCommunication.Profinet.Siemens;
using Prism.Events;
using Prism.Mvvm;
@@ -52,6 +53,11 @@ namespace CapMachine.Wpf.Services
/// </summary>
public SiemensS7Net SiemensDrive { get; set; }
/// <summary>
/// 三菱连接驱动程序
/// </summary>
public MelsecMcNet MelsecMcNetDrive { get; set; }
private bool _LinkState;
/// <summary>
/// PLC连接状态
@@ -123,6 +129,8 @@ namespace CapMachine.Wpf.Services
//stopwatch.Stop(); //停止Stopwatch
//Console.WriteLine("Add Elapsed output runTime:{0}", stopwatch.Elapsed.ToString());
//MelsecMcNetDrive.
//事件服务
_EventAggregator = eventAggregator;
AlarmService = alarmService;
@@ -149,7 +157,7 @@ namespace CapMachine.Wpf.Services
TagManger.AddTag(new Tag<short>("COND2压力", "COND2压力[BarA]", "Cond2Press", "程序", "VW15012", 100, 0, 100, "BarA", new ShortTagValue(), false) { DecimalPoint = 2 });
TagManger.AddTag(new Tag<short>("OCR", "OCR[%]", "OCR", "程序", "VW15014", 100, 0, 10, "%", new ShortTagValue(), true) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("HV[V]", "HV[V]", "HV", "程序", "VW15016", 100, 0, 10, "V", new ShortTagValue(), true) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("HV[A]", "HV[A]", "HVCur", "程序", "VW15018", 100, 0, 1, "A", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("HV[A]", "HV[A]", "HVCur", "程序", "VW15018", 100, 0, 100, "A", new ShortTagValue(), false) { DecimalPoint = 2 });
TagManger.AddTag(new Tag<short>("HV[W]", "HV[W]", "HVPw", "程序", "VW15020", 100, 0, 1, "W", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("LV[V]", "LV[V]", "LV", "程序", "VW15022", 100, 0, 10, "V", new ShortTagValue(), true) { DecimalPoint = 1 });
//TagManger.AddTag(new Tag<short>("LV[A]", "LV[A]", "LVCur", "程序", "VW15024", 100, 0, 1, "A", new ShortTagValue(), false) { DecimalPoint = 1 });
@@ -163,7 +171,7 @@ namespace CapMachine.Wpf.Services
TagManger.AddTag(new Tag<short>("EVAP出口温度", "EVAP出口温度[℃]", "EVAPExpTemp", "程序", "VW15036", 100, 0, 10, "℃", new ShortTagValue(), false) { DecimalPoint = 1 });
//TagManger.AddTag(new Tag<short>("冷媒流量", "冷媒流量[L/min]", "VRV", "程序", "VW15038", 100, 0, 1, "L/min", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("冷媒流量", "冷媒流量[L/min]", "VRV", "程序", "VW15038", 100, 0, 10, "L/min", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("润滑油流量", "润滑油流量[L/min]", "LubeFlow", "程序", "VW15040", 100, 0, 1, "L/min", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("润滑油流量", "润滑油流量[L/min]", "LubeFlow", "程序", "VW15040", 100, 0, 10, "L/min", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("排气温度", "排气温度[℃]", "ExTemp", "程序", "VW15042", 100, 0, 10, "℃", new ShortTagValue(), true) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("膨胀阀前压力", "膨胀阀前压力[BarA]", "TxvFrPress", "程序", "VW15044", 100, 0, 100, "BarA", new ShortTagValue(), false) { DecimalPoint = 2 });
TagManger.AddTag(new Tag<short>("膨胀阀前温度", "膨胀阀前温度[℃]", "TxvFrTemp", "程序", "VW15046", 100, 0, 10, "℃", new ShortTagValue(), false) { DecimalPoint = 1 });
@@ -173,18 +181,18 @@ namespace CapMachine.Wpf.Services
TagManger.AddTag(new Tag<short>("PTC流量", "PTC流量[L/min]", "PTCFlow", "程序", "VW15054", 100, 0, 1, "L/min", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("PTC入水温度", "PTC入水温度[℃]", "PTCEntTemp", "程序", "VW15056", 100, 0, 10, "℃", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("PTC出水温度", "PTC出水温度[℃]", "PTCExpTemp", "程序", "VW15058", 100, 0, 10, "℃", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯Cmp母线电流", "通讯Cmp母线电流[A]", "ComCapBusCur", "程序", "VW15060", 100, 0, 1, "A", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯Cmp母线电流", "通讯Cmp母线电流[A]", "ComCapBusCur", "程序", "VW15060", 100, 0, 100, "A", new ShortTagValue(), false) { DecimalPoint = 2 });
TagManger.AddTag(new Tag<short>("通讯Cmp母线电压", "通讯Cmp母线电压[V]", "ComCapBusVol", "程序", "VW15062", 100, 0, 10, "V", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯Cmp逆变器温度", "通讯Cmp逆变器温度[℃]", "ComCapInvTemp", "程序", "VW15064", 100, 0, 10, "℃", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯Cmp相电流", "通讯Cmp相电流[A]", "ComCapPhCur", "程序", "VW15066", 100, 0, 1, "A", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯Cmp逆变器温度", "通讯Cmp逆变器温度[℃]", "ComCapInvTemp", "程序", "VW15064", 100, 0, 1, "℃", new ShortTagValue(), false) { DecimalPoint = 0 });
TagManger.AddTag(new Tag<short>("通讯Cmp相电流", "通讯Cmp相电流[A]", "ComCapPhCur", "程序", "VW15066", 100, 0, 100, "A", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯Cmp功率", "通讯Cmp功率[W]", "ComCapPw", "程序", "VW15068", 100, 0, 1, "W", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯Cmp芯片温度", "通讯Cmp芯片温度[℃]", "ComCapChipTemp", "程序", "VW15070", 100, 0, 10, "℃", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯Cmp芯片温度", "通讯Cmp芯片温度[℃]", "ComCapChipTemp", "程序", "VW15070", 100, 0, 1, "℃", new ShortTagValue(), false) { DecimalPoint = 0 });
TagManger.AddTag(new Tag<short>("通讯PTC入水温度", "通讯PTC入水温度[℃]", "ComPTCEntTemp", "程序", "VW15072", 100, 0, 10, "℃", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯PTC出水温度", "通讯PTC出水温度[℃]", "ComPTCExpTemp", "程序", "VW15074", 100, 0, 10, "℃", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯PTC峰值电流", "通讯PTC峰值电流[A]", "ComPTCPeakCur", "程序", "VW15076", 100, 0, 1, "A", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯PTC母线电流", "通讯PTC母线电流[A]", "ComPTCBusCur", "程序", "VW15078", 100, 0, 1, "A", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯PTC膜温", "通讯PTC膜温[℃]", "ComPTCFlmTemp", "程序", "VW15080", 100, 0, 10, "℃", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯PTC模块温度", "通讯PTC模块温度[℃]", "ComPTCMdTemp", "程序", "VW15082", 100, 0, 10, "℃", new ShortTagValue(), false) { DecimalPoint = 1 });
TagManger.AddTag(new Tag<short>("通讯PTC膜温", "通讯PTC膜温[℃]", "ComPTCFlmTemp", "程序", "VW15080", 100, 0, 1, "℃", new ShortTagValue(), false) { DecimalPoint = 0 });
TagManger.AddTag(new Tag<short>("通讯PTC模块温度", "通讯PTC模块温度[℃]", "ComPTCMdTemp", "程序", "VW15082", 100, 0, 1, "℃", new ShortTagValue(), false) { DecimalPoint = 0 });
#endregion
@@ -1042,6 +1050,7 @@ namespace CapMachine.Wpf.Services
private void InitialPLCCom()
{
var IPInfo = ConfigHelper.GetValue("PLCIP");
SiemensDrive = new SiemensS7Net(SiemensPLCS.S200Smart, IPInfo);
// 连接对象

View File

@@ -1,8 +1,27 @@
using System;
using AutoMapper;
using CapMachine.Model;
using CapMachine.Shared.Controls;
using CapMachine.Wpf.ChannelModel;
using CapMachine.Wpf.Dtos;
using CapMachine.Wpf.Models;
using CapMachine.Wpf.Models.ProModelPars;
using CapMachine.Wpf.Models.Tag;
using CapMachine.Wpf.PrismEvent;
using CapMachine.Wpf.ProPars;
using CapMachine.Wpf.Tool;
using ImTools;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
using static CapMachine.Wpf.Models.ComEnum;
using System.Windows.Forms;
using HslCommunication.Profinet.Siemens;
using Masuit.Tools.Hardware;
namespace CapMachine.Wpf.Services
{
@@ -15,11 +34,665 @@ namespace CapMachine.Wpf.Services
/// <summary>
/// 实例化函数
/// </summary>
public ProRuntimeService()
public ProRuntimeService(IFreeSql freeSql, IMapper mapper, MachineRtDataService machineRtDataService, ILogService logService)
{
FreeSql = freeSql;
Mapper = mapper;
MachineRtDataService = machineRtDataService;
LogService = logService;
//实例化函数
ListProExModel = new List<ProExModel>()
{
new ProExModel(ProRunChannel){
MeterName="速度",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="COND1温度",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="COND2温度",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="COND2压力",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="EVAP出口温度",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="排气压力",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="HV电压",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="吸气压力",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="吸气温度",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="润滑油压力",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="LV电压",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="OCR",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="OS1温度",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="OS2温度",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="PTC入口温度",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="PTC流量",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="PTC功率",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="压缩机环境湿度",
ListProStepExe=new List<ProStepExe>(),
},
new ProExModel(ProRunChannel){
MeterName="压缩机环境温度",
ListProStepExe=new List<ProStepExe>(),
}
};
//驱动实例
SiemensDrive = MachineRtDataService.SiemensDrive;
//程序运行实时管道数据监听
Task.Run(() => ListenProRunChannelAction());
}
/// <summary>
/// 选中的程序运行集合
/// </summary>
public List<ProSegRun> SelectedListProSegRun { get; set; }
public IFreeSql FreeSql { get; }
public IMapper Mapper { get; }
public MachineRtDataService MachineRtDataService { get; }
public ILogService LogService { get; }
/// <summary>
/// 西门子连接驱动程序
/// </summary>
public SiemensS7Net SiemensDrive { get; set; }
/// <summary>
/// Task扫描 程序运行时间扫描任务
/// </summary>
private static Task ProRunTimeScanTask { get; set; }
/// <summary>
/// 程序运行集合
/// </summary>
public List<ProExModel> ListProExModel { get; set; }
/// <summary>
/// PLC加载配置数据集合
/// </summary>
public List<PlcLoadConfigCell> ListPlcLoadConfigCell { get; set; }
/// <summary>
/// 加载选中的程序运行集合
/// </summary>
public void LoadProSegRun(List<ProSegRun> SelectedListProSegRun)
{
if (SelectedListProSegRun == null || SelectedListProSegRun.Count() == 0)
{
return;
}
//先清空之前的步骤数据
foreach (var itemProExModel in ListProExModel)
{
itemProExModel.ListProStepExe.Clear();
}
//多个选中的程序块循环
foreach (var itemProSegRun in SelectedListProSegRun)
{
//获取当前程序块
//逐个对应的程序
var CurProgramSeg = FreeSql.Select<ProgramSeg>(itemProSegRun.ProgramSegId)
.IncludeMany(a => a.ProSteps,
then => then.IncludeMany(b => b.MeterSpeeds)
.IncludeMany(b => b.MeterCond1Temps)
.IncludeMany(b => b.MeterCond2Temps)
.IncludeMany(b => b.MeterCond2Presss)
.IncludeMany(b => b.MeterEVAPExpTemps)
.IncludeMany(b => b.MeterExPresss)
.IncludeMany(b => b.MeterHVVols)
.IncludeMany(b => b.MeterInhPresss)
.IncludeMany(b => b.MeterInhTemps)
.IncludeMany(b => b.MeterLubePresss)
.IncludeMany(b => b.MeterLVVols)
.IncludeMany(b => b.MeterOCRs)
.IncludeMany(b => b.MeterOS1Temps)
.IncludeMany(b => b.MeterOS2Temps)
.IncludeMany(b => b.MeterPTCEntTemps)
.IncludeMany(b => b.MeterPTCFlows)
.IncludeMany(b => b.MeterPTCPws)
.IncludeMany(b => b.MeterEnvRHs)
.IncludeMany(b => b.MeterEnvTemps)
).ToList().FirstOrDefault();
//获取当前的程序
if (CurProgramSeg != null && CurProgramSeg.ProSteps != null && CurProgramSeg.ProSteps.Any())
{
//CurProgramSeg有重复运行的次数
for (int SegIndex = 0; SegIndex < CurProgramSeg.ProRepeat; SegIndex++)
{
//解析程序的多行步骤,表格中的行步骤数据,牟定速度
foreach (var itemStep in CurProgramSeg.ProSteps.OrderBy(a => a.StepNo))
{
//单行步骤中包含多个仪表参数的配置,需要逐个仪表参数手动操作解析
//********* 单个速度步骤信息的解析 *********
var CurMeterName = "速度";
if (itemStep.MeterSpeeds != null && itemStep.MeterSpeeds.Any())
{
switch (itemStep.MeterSpeeds.FirstOrDefault()!.ValueType)
{
case ConfigValueType.Constant: //常值
//常值的话就一个数据,循环执行一次
foreach (var itemMeterValueCell in itemStep.MeterSpeeds)
{
var Pid = new ConfigPID();
if (FreeSql.Select<ConfigPID>().Where(a => a.MeterName == CurMeterName && a.IndexNo == itemMeterValueCell.ParNo).Any())
{
Pid = FreeSql.Select<ConfigPID>().Where(a => a.MeterName == CurMeterName && a.IndexNo == itemMeterValueCell.ParNo).First();
}
var Limit = new ConfigLimit();
if (FreeSql.Select<ConfigLimit>().Where(a => a.MeterName == CurMeterName && a.IndexNo == itemMeterValueCell.Ev).Any())
{
Limit = FreeSql.Select<ConfigLimit>().Where(a => a.MeterName == CurMeterName && a.IndexNo == itemMeterValueCell.Ev).First();
}
var Alarm = new ConfigAlarm();
if (FreeSql.Select<ConfigAlarm>().Where(a => a.MeterName == CurMeterName && a.IndexNo == itemMeterValueCell.Ev).Any())
{
Alarm = FreeSql.Select<ConfigAlarm>().Where(a => a.MeterName == CurMeterName && a.IndexNo == itemMeterValueCell.Ev).First();
}
ListProExModel.FindFirst(a => a.MeterName == CurMeterName).ListProStepExe.Add(new ProStepExe()
{
//程序块
ProSegName = CurProgramSeg.Name,
ProSegStep = SegIndex,
ProSegRepeat = CurProgramSeg.ProRepeat,
ProSegIsExeing = false,//配置阶段默认不执行 false
//程序步骤数据
StartSV = GetSVByProcess(itemMeterValueCell.Constant, CurMeterName),
EndSV = GetSVByProcess(itemMeterValueCell.Constant, CurMeterName),
KeepTime = itemMeterValueCell.KeepTime,
MeterStepIsExeing = false,//配置阶段默认不执行 false
MeterStepIsOK = false,//配置阶段默认不完成 false
ExistSlop = false,//常值没有斜率 //开始和结束不一样则存在斜率
MeterStep = ListProExModel.FindFirst(a => a.MeterName == CurMeterName).ListProStepExe.Count + 1,
MeterName = CurMeterName,
LimitNo = itemMeterValueCell.ParNo,
AlarmNo = itemMeterValueCell.Ev,
PIDNo = itemMeterValueCell.Ev,
CurConfigPIDDto = Mapper.Map<ConfigPIDDto>(Pid),
CurConfigLimitDto = Mapper.Map<ConfigLimitDto>(Limit),
ProStepInfo = $"{itemStep.StepNo}-{itemMeterValueCell.StepNo}",
});
}
break;
case ConfigValueType.Slope: //斜率
//根据循环次数确定
for (int StepIndex = 0; StepIndex < itemStep.SpeedCycle; StepIndex++)
{
//根据循环次数执行
foreach (var itemMeterValueCell in itemStep.MeterSpeeds)
{
var Pid = new ConfigPID();
if (FreeSql.Select<ConfigPID>().Where(a => a.MeterName == CurMeterName && a.IndexNo == itemMeterValueCell.ParNo).Any())
{
Pid = FreeSql.Select<ConfigPID>().Where(a => a.MeterName == CurMeterName && a.IndexNo == itemMeterValueCell.ParNo).First();
}
var Limit = new ConfigLimit();
if (FreeSql.Select<ConfigLimit>().Where(a => a.MeterName == CurMeterName && a.IndexNo == itemMeterValueCell.Ev).Any())
{
Limit = FreeSql.Select<ConfigLimit>().Where(a => a.MeterName == CurMeterName && a.IndexNo == itemMeterValueCell.Ev).First();
}
var Alarm = new ConfigAlarm();
if (FreeSql.Select<ConfigAlarm>().Where(a => a.MeterName == CurMeterName && a.IndexNo == itemMeterValueCell.Ev).Any())
{
Alarm = FreeSql.Select<ConfigAlarm>().Where(a => a.MeterName == CurMeterName && a.IndexNo == itemMeterValueCell.Ev).First();
}
ListProExModel.FindFirst(a => a.MeterName == CurMeterName).ListProStepExe.Add(new ProStepExe()
{
//程序块
ProSegName = CurProgramSeg.Name,
ProSegStep = SegIndex,
ProSegRepeat = CurProgramSeg.ProRepeat,
ProSegIsExeing = false,//配置阶段默认不执行 false
//程序步骤数据
//SV = CALCHelper.GetQuickSV(itemMeterValueCell.Constant, 1),
StartSV = GetSVByProcess(itemMeterValueCell.StartValue, CurMeterName),
EndSV = GetSVByProcess(itemMeterValueCell.EndValue, CurMeterName),
KeepTime = itemMeterValueCell.KeepTime,
MeterStepIsExeing = false,//配置阶段默认不执行 false
MeterStepIsOK = false,//配置阶段默认不完成 false
ExistSlop = itemMeterValueCell.StartValue == itemMeterValueCell.EndValue ? false : true,//开始和结束不一样则存在斜率
MeterStep = ListProExModel.FindFirst(a => a.MeterName == CurMeterName).ListProStepExe.Count + 1,
LimitNo = itemMeterValueCell.ParNo,
AlarmNo = itemMeterValueCell.ParNo,
PIDNo = itemMeterValueCell.Ev,
CurConfigPIDDto = Mapper.Map<ConfigPIDDto>(Pid),
CurConfigLimitDto = Mapper.Map<ConfigLimitDto>(Limit),
ProStepInfo = $"{itemStep.StepNo}-{itemMeterValueCell.StepNo}",
MeterName = CurMeterName,
});
}
}
break;
default:
break;
}
}
}
}
}
}
StartProRun();
}
/// <summary>
/// 处理后获取SV的数据
/// </summary>
/// <returns></returns>
private int GetSVByProcess(double SV, string Name)
{
var Data = ListPlcLoadConfigCell.Where(a => a.Name == Name);
if (Data.Any())
{
return (int)(SV / (Data.FirstOrDefault()!.Precision));
}
else
{
LogService.Warn($"【名称】: {Name} - 未找到对应的参数配置,数据转换格式失败");
//未找到的话,则直接返回
return (int)SV;
}
}
#region
/// <summary>
/// 开始程序调度运行
/// </summary>
public void StartProRun()
{
//开始运行前的需要进行一些设置和数据初始化
foreach (var itemProExModel in ListProExModel)
{
//被启用和有步骤时才进行运行设置
if (itemProExModel == null && itemProExModel.Enable && itemProExModel!.ListProStepExe.Count() > 0) continue;
itemProExModel.RunEnable = true;
//设置下一步数据是第一步数据,然后设置时间
itemProExModel.NextProStepExe = itemProExModel!.ListProStepExe.OrderBy(a => a.MeterStep).FirstOrDefault()!;
itemProExModel.CurProStepExe = new ProStepExe();
itemProExModel.StepEndDt = DateTime.Now;
}
//运行扫描任务
ProRunTimeScan();
}
private bool ProRunTaskEnable = true;
/// <summary>
/// 运行时间扫描
/// </summary>
private void ProRunTimeScan()
{
ProRunTimeScanTask = Task.Run(async () =>
{
while (ProRunTaskEnable)
{
try
{
//循环给模型的当前时间赋值,驱动步骤执行
foreach (var itemProExModel in ListProExModel)
{
if (itemProExModel.RunEnable)
{
itemProExModel.CurrentDateTime = DateTime.Now;
}
}
await Task.CompletedTask;
}
catch (Exception ex)
{
//LogService.Info($"时间:{DateTime.Now.ToString()}-【Meter】-{ex.Message}");
}
//Console.WriteLine($"扫描时间:{DiagnosticsTime.Elapsed.TotalMilliseconds.ToString()}");
}
});
}
/// <summary>
/// 队列通道
/// 当前队列消费触发的数据记录
/// </summary>
public Channel<ProRunChannelData> ProRunChannel = Channel.CreateUnbounded<ProRunChannelData>(new UnboundedChannelOptions()
{
SingleWriter = false,//允许一次写入多条数据
SingleReader = true //一次只能读取一条消息
});
/// <summary>
/// 程序执行管道监听方法
/// </summary>
/// <exception cref="NotImplementedException"></exception>
private async void ListenProRunChannelAction()
{
while (await ProRunChannel.Reader.WaitToReadAsync())
{
if (ProRunChannel.Reader.TryRead(out var ProRunChannelData))
{
////第一次计时
//stopwatch.Start(); //启动Stopwatch
if (ProRunChannelData.RunStepType == RunStepType.SlopCell)
{
Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} " +
$"【参数名称】:{ProRunChannelData.MeterName} " +
$"【程序Seg】{ProRunChannelData.ProSegName} " +
$"【程序步骤】{ProRunChannelData.MeterStep} " +
$"【斜坡打点步骤】{ProRunChannelData.SlopStepNo} " +
$"【斜坡打点值SV】{ProRunChannelData.SV} " +
$"【Msg】接受到仿真写入PLC OK ");
}
else
{
Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} " +
$"【参数名称】:{ProRunChannelData.MeterName} " +
$"【程序Seg】{ProRunChannelData.ProSegName} " +
$"【程序步骤】{ProRunChannelData.MeterStep} " +
$"【步骤SV】{ProRunChannelData.SV} " +
$"【Msg】接受到步骤仿真写入PLC OK ");
}
Thread.Sleep(50);
//DownLoadPID();
//stopwatch.Stop(); //停止Stopwatch
//Console.WriteLine("保存数据耗时::{0}", stopwatch.Elapsed.TotalSeconds.ToString());
//stopwatch.Reset();
}
}
}
///// <summary>
///// 下载PID 信息
///// </summary>
//private void DownLoadPID(ProExModel ProExecuteModel)
//{
// //上一次PID信息不为空的话则进行比较后再下载
// if (ProExecuteModel != null && ProExecuteModel.CurProStepExe != null && ProExecuteModel.LastProStepExe != null)
// {
// //判断是否比较PID信息
// if (ProExecuteModel.CurProStepExe.PIDNo != ProExecuteModel.LastProStepExe.PIDNo)
// {
// //进行比较跟上一个是否相同
// if (ProExecuteModel.CurProStepExe != ProExecuteModel.LastProStepExe)
// {
// var PlcLoadConfigCell_P = ProExecuteModel.ListPlcLoadConfigCell.First(a => a.Name == "P")!;
// var PlcLoadConfigCell_I = ProExecuteModel.ListPlcLoadConfigCell.First(a => a.Name == "I")!;
// var PlcLoadConfigCell_D = ProExecuteModel.ListPlcLoadConfigCell.First(a => a.Name == "D")!;
// //下载PID信息的P
// var ResultP = SiemensDrive.Write(PlcLoadConfigCell_P!.Address, (double)ProExecuteModel.CurProStepExe.CurConfigPIDDto!.P * 1.0 / PlcLoadConfigCell_P.Precision);
// Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{ProExecuteModel.MeterName} " +
// $"【程序Seg】{ProExecuteModel.CurProStepExe.ProSegName} " +
// $"【程序步骤】{ProExecuteModel.CurProStepExe.MeterStep} " +
// $"【类型】:{ProExecuteModel.CurProStepExe.ExistSlop.ToString()} " +
// $"【参数】PID-P " +
// $"【值】:{ProExecuteModel.CurProStepExe.CurConfigPIDDto!.P}" +
// $"【Msg】{ResultP.Message} ");
// //下载PID信息的I
// var ResultI = SiemensDrive.Write(PlcLoadConfigCell_I!.Address, (double)ProExecuteModel.CurProStepExe.CurConfigPIDDto!.I * 1.0 / PlcLoadConfigCell_I.Precision);
// Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{ProExecuteModel.MeterName} " +
// $"【程序Seg】{ProExecuteModel.CurProStepExe.ProSegName} " +
// $"【程序步骤】{ProExecuteModel.CurProStepExe.MeterStep} " +
// $"【类型】:{ProExecuteModel.CurProStepExe.ExistSlop.ToString()} " +
// $"【参数】PID-I " +
// $"【值】:{ProExecuteModel.CurProStepExe.CurConfigPIDDto!.I}" +
// $"【Msg】{ResultI.Message} ");
// //下载PID信息的D
// var ResultD = SiemensDrive.Write(PlcLoadConfigCell_D!.Address, (double)ProExecuteModel.CurProStepExe.CurConfigPIDDto!.D * 1.0 / PlcLoadConfigCell_D.Precision);
// Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{ProExecuteModel.MeterName} " +
// $"【程序Seg】{ProExecuteModel.CurProStepExe.ProSegName} " +
// $"【程序步骤】{ProExecuteModel.CurProStepExe.MeterStep} " +
// $"【类型】:{ProExecuteModel.CurProStepExe.ExistSlop.ToString()} " +
// $"【参数】PID-D " +
// $"【值】:{ProExecuteModel.CurProStepExe.CurConfigPIDDto!.D}" +
// $"【Msg】{ResultD.Message} ");
// return;
// }
// //相同的则不需要下载,直接使用上一个的配置
// return;
// }
// }
// else//Pid为空的话直接下载可能是第一个步骤
// {
// var PlcLoadConfigCell_P = ProExecuteModel!.ListPlcLoadConfigCell.First(a => a.Name == "P")!;
// var PlcLoadConfigCell_I = ProExecuteModel.ListPlcLoadConfigCell.First(a => a.Name == "I")!;
// var PlcLoadConfigCell_D = ProExecuteModel.ListPlcLoadConfigCell.First(a => a.Name == "D")!;
// //下载PID信息的P
// var ResultP = SiemensDrive.Write(PlcLoadConfigCell_P!.Address, (double)ProExecuteModel.CurProStepExe.CurConfigPIDDto!.P * 1.0 / PlcLoadConfigCell_P.Precision);
// Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{ProExecuteModel.MeterName} " +
// $"【程序Seg】{ProExecuteModel.CurProStepExe.ProSegName} " +
// $"【程序步骤】{ProExecuteModel.CurProStepExe.MeterStep} " +
// $"【类型】:{ProExecuteModel.CurProStepExe.ExistSlop.ToString()} " +
// $"【参数】PID-P " +
// $"【值】:{ProExecuteModel.CurProStepExe.CurConfigPIDDto!.P}" +
// $"【Msg】{ResultP.Message} ");
// //下载PID信息的I
// var ResultI = SiemensDrive.Write(PlcLoadConfigCell_I!.Address, (double)ProExecuteModel.CurProStepExe.CurConfigPIDDto!.I * 1.0 / PlcLoadConfigCell_I.Precision);
// Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{ProExecuteModel.MeterName} " +
// $"【程序Seg】{ProExecuteModel.CurProStepExe.ProSegName} " +
// $"【程序步骤】{ProExecuteModel.CurProStepExe.MeterStep} " +
// $"【类型】:{ProExecuteModel.CurProStepExe.ExistSlop.ToString()} " +
// $"【参数】PID-I " +
// $"【值】:{ProExecuteModel.CurProStepExe.CurConfigPIDDto!.I}" +
// $"【Msg】{ResultI.Message} ");
// //下载PID信息的D
// var ResultD = SiemensDrive.Write(PlcLoadConfigCell_D!.Address, (double)ProExecuteModel.CurProStepExe.CurConfigPIDDto!.D * 1.0 / PlcLoadConfigCell_D.Precision);
// Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{ProExecuteModel.MeterName} " +
// $"【程序Seg】{ProExecuteModel.CurProStepExe.ProSegName} " +
// $"【程序步骤】{ProExecuteModel.CurProStepExe.MeterStep} " +
// $"【类型】:{ProExecuteModel.CurProStepExe.ExistSlop.ToString()} " +
// $"【参数】PID-D " +
// $"【值】:{ProExecuteModel.CurProStepExe.CurConfigPIDDto!.D}" +
// $"【Msg】{ResultD.Message} ");
// return;
// }
//}
///// <summary>
///// 下载Limit 信息
///// </summary>
//private void DownLoadLimit(ProExModel ProExecuteModel)
//{
// //上一次Limit信息不为空的话则进行比较后再下载
// if (ProExecuteModel != null && ProExecuteModel.CurProStepExe != null && ProExecuteModel.LastProStepExe != null)
// {
// //判断是否比较Limit信息
// if (ProExecuteModel.CurProStepExe.LimitNo != ProExecuteModel.LastProStepExe.LimitNo)
// {
// //进行比较跟上一个是否相同
// if (ProExecuteModel.CurProStepExe != ProExecuteModel.LastProStepExe)
// {
// var PlcLoadConfigCell_Up = ProExecuteModel.ListPlcLoadConfigCell.First(a => a.Name == "Up")!;
// var PlcLoadConfigCell_Down = ProExecuteModel.ListPlcLoadConfigCell.First(a => a.Name == "Down")!;
// //下载Limit信息的Up
// var ResultUp = SiemensDrive.Write(PlcLoadConfigCell_Up!.Address, (double)ProExecuteModel.CurProStepExe.CurConfigLimitDto!.Up * 1.0 / PlcLoadConfigCell_Up.Precision);
// Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{ProExecuteModel.MeterName} " +
// $"【程序Seg】{ProExecuteModel.CurProStepExe.ProSegName} " +
// $"【程序步骤】{ProExecuteModel.CurProStepExe.MeterStep} " +
// $"【类型】:{ProExecuteModel.CurProStepExe.ExistSlop.ToString()} " +
// $"【参数】Limit-Up " +
// $"【值】:{ProExecuteModel.CurProStepExe.CurConfigLimitDto!.Up}" +
// $"【Msg】{ResultUp.Message} ");
// //下载Limit信息的Down
// var ResultDown = SiemensDrive.Write(PlcLoadConfigCell_Down!.Address, (double)ProExecuteModel.CurProStepExe.CurConfigLimitDto!.Down * 1.0 / PlcLoadConfigCell_Down.Precision);
// Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{ProExecuteModel.MeterName} " +
// $"【程序Seg】{ProExecuteModel.CurProStepExe.ProSegName} " +
// $"【程序步骤】{ProExecuteModel.CurProStepExe.MeterStep} " +
// $"【类型】:{ProExecuteModel.CurProStepExe.ExistSlop.ToString()} " +
// $"【参数】Limit-Down " +
// $"【值】:{ProExecuteModel.CurProStepExe.CurConfigLimitDto!.Down}" +
// $"【Msg】{ResultUp.Message} ");
// return;
// }
// //相同的则不需要下载,直接使用上一个的配置
// return;
// }
// }
// else//Pid为空的话直接下载可能是第一个步骤
// {
// var PlcLoadConfigCell_Up = ProExecuteModel.ListPlcLoadConfigCell.First(a => a.Name == "Up")!;
// var PlcLoadConfigCell_Down = ProExecuteModel.ListPlcLoadConfigCell.First(a => a.Name == "Down")!;
// //下载Limit信息的Up
// var ResultUp = SiemensDrive.Write(PlcLoadConfigCell_Up!.Address, (double)ProExecuteModel.CurProStepExe.CurConfigLimitDto!.Up * 1.0 / PlcLoadConfigCell_Up.Precision);
// Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{ProExecuteModel.MeterName} " +
// $"【程序Seg】{ProExecuteModel.CurProStepExe.ProSegName} " +
// $"【程序步骤】{ProExecuteModel.CurProStepExe.MeterStep} " +
// $"【类型】:{ProExecuteModel.CurProStepExe.ExistSlop.ToString()} " +
// $"【参数】Limit-Up " +
// $"【值】:{ProExecuteModel.CurProStepExe.CurConfigLimitDto!.Up}" +
// $"【Msg】{ResultUp.Message} ");
// //下载Limit信息的Down
// var ResultDown = SiemensDrive.Write(PlcLoadConfigCell_Down!.Address, (double)ProExecuteModel.CurProStepExe.CurConfigLimitDto!.Down * 1.0 / PlcLoadConfigCell_Down.Precision);
// Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{ProExecuteModel.MeterName} " +
// $"【程序Seg】{ProExecuteModel.CurProStepExe.ProSegName} " +
// $"【程序步骤】{ProExecuteModel.CurProStepExe.MeterStep} " +
// $"【类型】:{ProExecuteModel.CurProStepExe.ExistSlop.ToString()} " +
// $"【参数】Limit-Down " +
// $"【值】:{ProExecuteModel.CurProStepExe.CurConfigLimitDto!.Down}" +
// $"【Msg】{ResultUp.Message} ");
// return;
// }
//}
///// <summary>
///// 下载SV 信息
///// </summary>
///// <param name="ProExecuteModel"></param>
//private void DownLoadSV(ProExModel ProExecuteModel)
//{
// //上一次SV信息不为空的话则进行比较后再下载
// if (ProExecuteModel != null && ProExecuteModel.CurProStepExe != null && ProExecuteModel.LastProStepExe != null)
// {
// //判断比较SV信息
// if (ProExecuteModel.CurProStepExe.EndSV != ProExecuteModel.LastProStepExe.EndSV)
// {
// //SV配置
// var PlcLoadConfigCell_SV = ProExecuteModel.ListPlcLoadConfigCell.First(a => a.Name == "SV")!;
// //下载SV信息的
// var ResultSV = SiemensDrive.Write(PlcLoadConfigCell_SV!.Address, (double)ProExecuteModel.CurProStepExe.EndSV * 1.0 / PlcLoadConfigCell_SV.Precision);
// Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{ProExecuteModel.MeterName} " +
// $"【程序Seg】{ProExecuteModel.CurProStepExe.ProSegName} " +
// $"【程序步骤】{ProExecuteModel.CurProStepExe.MeterStep} " +
// $"【类型】:{ProExecuteModel.CurProStepExe.ExistSlop.ToString()} " +
// $"【参数】SV " +
// $"【值】:{ProExecuteModel.CurProStepExe.CurConfigLimitDto!.Up}" +
// $"【Msg】{ResultSV.Message} ");
// return;
// }
// else
// {
// //跟上一次的一样,不需要下载了
// }
// }
// else//Pid为空的话直接下载可能是第一个步骤
// {
// //SV配置
// var PlcLoadConfigCell_SV = ProExecuteModel.ListPlcLoadConfigCell.First(a => a.Name == "SV")!;
// //下载SV信息的
// var ResultSV = SiemensDrive.Write(PlcLoadConfigCell_SV!.Address, (double)ProExecuteModel.CurProStepExe.EndSV * 1.0 / PlcLoadConfigCell_SV.Precision);
// Console.WriteLine($"【时间】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 【参数名称】:{ProExecuteModel.MeterName} " +
// $"【程序Seg】{ProExecuteModel.CurProStepExe.ProSegName} " +
// $"【程序步骤】{ProExecuteModel.CurProStepExe.MeterStep} " +
// $"【类型】:{ProExecuteModel.CurProStepExe.ExistSlop.ToString()} " +
// $"【参数】SV " +
// $"【值】:{ProExecuteModel.CurProStepExe.CurConfigLimitDto!.Up}" +
// $"【Msg】{ResultSV.Message} ");
// return;
// }
//}
#endregion
}
}

View File

@@ -0,0 +1,287 @@
using CapMachine.Model;
using CapMachine.Wpf.Models.ProModelPars;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CapMachine.Wpf.Tool
{
public class CALCHelper
{
/// <summary>
/// 计算斜率-分
/// </summary>
public static int GetSlop(double Value1, double Value2, int TimeSed)
{
var diff = Value2 - Value1;
var TimeMin = TimeSed * 1.0 / 60;
if (TimeSed == 0) return 0;
var Result = (int)Math.Ceiling(diff / TimeMin);
if (Result > 9999)
{
return 9999;
}
if (Result < -1999)
{
return -1999;
}
return Result;
}
/// <summary>
/// 计算斜率-秒-DB表
/// </summary>
public static int GetSlopSed(double Value1, double Value2, int TimeSed)
{
var diff = Value2 - Value1;
//var TimeMin = TimeSed * 1.0 / 60;
if (TimeSed == 0) return 0;//0应该是OFF功能
var Result = diff / TimeSed;
if (Result > 2000)
{
return 2000;
}
if (Result < -1999.9)
{
return -1999;
}
if (Result >= 0)
{
return (int)Math.Ceiling(Result);//乘以10是DB表的通信上的范围数据要求的实际显示x.x
}
else
{
return (int)Math.Floor(Result);//乘以10是DB表的通信上的范围数据要求的实际显示x.x
}
//return (int)Math.Ceiling(Result);//乘以10是DB表的通信上的范围数据要求的实际显示x.x
}
/// <summary>
/// 计算斜率-分鐘-DB表
/// </summary>
public static int GetSlopMinute(double Value1, double Value2, int TimeSed)
{
var diff = Value2 - Value1;
var TimeMin = TimeSed * 1.0 / 60;
if (TimeSed == 0) return 0;//0应该是OFF功能
var Result = diff / TimeMin;
if (Result > 2000)
{
return 2000;
}
if (Result < -1999.9)
{
return -1999;
}
if (Result >= 0)
{
return (int)Math.Ceiling(Result * 10);//乘以10是DB表的通信上的范围数据要求的实际显示x.x
}
else
{
return (int)Math.Floor(Result * 10);//乘以10是DB表的通信上的范围数据要求的实际显示x.x
}
}
/// <summary>
/// 计算斜率-小时-DB表
/// </summary>
public static int GetSlopHour(double Value1, double Value2, int TimeSed)
{
var diff = Value2 - Value1;
var TimeHour = TimeSed * 1.0 / 3600;
if (TimeSed == 0) return 0;//0应该是OFF功能
var Result = diff / TimeHour;
if (Result > 2000)
{
return 2000;
}
if (Result < -1999.9)
{
return -1999;
}
if (Result >= 0)
{
return (int)Math.Ceiling(Result);//乘以10是DB表的通信上的范围数据要求的实际显示x.x
}
else
{
return (int)Math.Floor(Result);//乘以10是DB表的通信上的范围数据要求的实际显示x.x
}
}
/// <summary>
/// 计算斜率-秒-DB表 CV
/// </summary>
public static int GetSlopCVMinute(double Value1, double Value2, int TimeSed)
{
var diff = Value2 - Value1;
//var TimeMin = TimeSed * 1.0 / 60;
if (TimeSed == 0) return 0;//0应该是OFF功能
var Result = diff / TimeSed;
if (Result > 2000)
{
return 2000;
}
if (Result < -1999.9)
{
return -1999;
}
if (Result >= 0)
{
return (int)Math.Ceiling(Result);//乘以10是DB表的通信上的范围数据要求的实际显示x.x
}
else
{
return (int)Math.Floor(Result);//乘以10是DB表的通信上的范围数据要求的实际显示x.x
}
}
///// <summary>
///// 计算斜率-秒-DB表
///// </summary>
//public static int GetSlopSed(double Value1, double Value2, int TimeSed)
//{
// var diff = Value2 - Value1;
// //var TimeMin = TimeSed * 1.0 / 60;
// if (TimeSed == 0) return 0;//0应该是OFF功能
// var Result = diff / TimeSed;
// if (Result > 2000)
// {
// return 2000 * 10;
// }
// if (Result < -1999.9)
// {
// return -1999 * 10;
// }
// return (int)Math.Ceiling(Result * 10);//乘以10是DB表的通信上的范围数据要求的实际显示x.x
//}
/// <summary>
/// SV值的数据获取
/// </summary>
/// <param name="sourceData"></param>
/// <param name="accuracy"></param>
/// <returns></returns>
public static int GetQuickSV(double sourceData, short accuracy)
{
return (int)(sourceData * (int)Math.Pow(10, accuracy));
}
/// <summary>
/// 比较是否有改变的数据
/// </summary>
/// <param name="NextData"></param>
/// <param name="CurrentData"></param>
/// <param name="Field"></param>
/// <returns></returns>
public static bool CpStepExecuteCompareInfo(ProStepExe NextData, ProStepExe CurrentData, string Field)
{
switch (Field)
{
case "PID":
if (NextData.PIDNo == CurrentData.PIDNo) return true;
return false;
case "SV":
if (NextData.EndSV == CurrentData.EndSV) return true;
return false;
case "Limit":
if (NextData.LimitNo == CurrentData.LimitNo) return true;
return false;
case "Alarm":
if (NextData.AlarmNo == CurrentData.AlarmNo) return true;
return false;
default:
return false;
}
}
/// <summary>
/// 比较是否有改变的数据
/// </summary>
/// <param name="NextData"></param>
/// <param name="CurrentData"></param>
/// <param name="Field"></param>
/// <returns></returns>
public static bool KpStepExecuteCompareInfo(ProStepExe NextData, ProStepExe CurrentData, string Field)
{
switch (Field)
{
case "PID":
if (NextData.PIDNo == CurrentData.PIDNo) return true;
return false;
case "SV":
if (NextData.EndSV == CurrentData.EndSV) return true;
return false;
case "Limit":
if (NextData.LimitNo == CurrentData.LimitNo) return true;
return false;
case "Alarm":
if (NextData.AlarmNo == CurrentData.AlarmNo) return true;
return false;
default:
return false;
}
}
/// <summary>
/// 判断Limit下载的次序
/// </summary>
/// <param name="NextData"></param>
/// <param name="CurrentData"></param>
/// <returns></returns>
public static int CpStepExecuteLimitCompareInfo(ProStepExe NextData, ProStepExe CurrentData)
{
if (NextData.CurConfigLimitDto.Down >= CurrentData.CurConfigLimitDto.Up)
{
//先下载Up,后下载Down
return 1;
}
if (NextData.CurConfigLimitDto.Up <= CurrentData.CurConfigLimitDto.Down)
{
//先下载Down,后下载Up
return 3;
}
//正常下载 Down和Up顺序都可以
return 2;
}
/// <summary>
/// 判断Limit下载的次序
/// </summary>
/// <param name="NextData"></param>
/// <param name="CurrentData"></param>
/// <returns></returns>
public static int KpStepExecuteLimitCompareInfo(ProStepExe NextData, ProStepExe CurrentData)
{
if (NextData.CurConfigLimitDto.Down >= CurrentData.CurConfigLimitDto.Up)
{
//先下载Up,后下载Down
return 1;
}
if (NextData.CurConfigLimitDto.Up <= CurrentData.CurConfigLimitDto.Down)
{
//先下载Down,后下载Up
return 3;
}
//正常下载 Down和Up顺序都可以
return 2;
}
//private long GetProDur(QuickStep quickStep)
//{
// return 0;
//}
}
}

View File

@@ -23,7 +23,7 @@ namespace CapMachine.Wpf.ViewModels
public class ProConfigViewModel : NavigationViewModel
{
public ProConfigViewModel(IDialogService dialogService, IFreeSql freeSql,
IEventAggregator eventAggregator, IRegionManager regionManager, SysRunService sysRunService, ConfigService configService,
IEventAggregator eventAggregator, IRegionManager regionManager, SysRunService sysRunService, ConfigService configService, ProRuntimeService proRuntimeService,
MachineRtDataService machineRtDataService)
{
//LogService = logService;
@@ -32,6 +32,7 @@ namespace CapMachine.Wpf.ViewModels
RegionManager = regionManager;
SysRunService = sysRunService;
ConfigService = configService;
ProRuntimeService = proRuntimeService;
this.MachineRtDataService = machineRtDataService;
//MachineDataService = machineDataService;
@@ -83,6 +84,7 @@ namespace CapMachine.Wpf.ViewModels
public IRegionManager RegionManager { get; }
public SysRunService SysRunService { get; }
public ConfigService ConfigService { get; }
public ProRuntimeService ProRuntimeService { get; }
private MachineRtDataService MachineRtDataService { get; }
/// <summary>
@@ -2327,48 +2329,50 @@ namespace CapMachine.Wpf.ViewModels
//返回的数据
List<PlcParsData> ReturnPlcParsData = new List<PlcParsData>();
//var Data=FreeSql.Select<ProSegRun>(
//以每个程序为单元循环执行
foreach (var item in ProSegRunListViewItems)
{
var FindData = FreeSql.Select<ProgramSeg>(item.ProgramSegId)
.IncludeMany(a => a.ProSteps,
then => then.IncludeMany(b => b.MeterSpeeds)
.IncludeMany(b => b.MeterCond1Temps)
.IncludeMany(b => b.MeterCond2Temps)
.IncludeMany(b => b.MeterCond2Presss)
.IncludeMany(b => b.MeterEVAPExpTemps)
.IncludeMany(b => b.MeterExPresss)
.IncludeMany(b => b.MeterHVVols)
.IncludeMany(b => b.MeterInhPresss)
.IncludeMany(b => b.MeterInhTemps)
.IncludeMany(b => b.MeterLubePresss)
.IncludeMany(b => b.MeterLVVols)
.IncludeMany(b => b.MeterOCRs)
.IncludeMany(b => b.MeterOS1Temps)
.IncludeMany(b => b.MeterOS2Temps)
.IncludeMany(b => b.MeterPTCEntTemps)
.IncludeMany(b => b.MeterPTCFlows)
.IncludeMany(b => b.MeterPTCPws)
.IncludeMany(b => b.MeterEnvRHs)
.IncludeMany(b => b.MeterEnvTemps)
).ToList().FirstOrDefault();
ProRuntimeService.LoadProSegRun(ProSegRunListViewItems.ToList());
if (FindData != null && FindData.ProSteps != null && FindData.ProSteps.Any())
{
//执行程序的步骤集合数据
ReturnPlcParsData = ProParsSongZhiHelper.GetPlcParsData(FindData.ProSteps, FindData.ProRepeat);
//把次数给PLC那么此时应该是最后一个程序给PLC了
ProParsSongZhiHelper.LoadProCycleToPlc(MachineRtDataService.SiemensDrive, FindData.ProRepeat);
}
}
////var Data=FreeSql.Select<ProSegRun>(
////以每个程序为单元循环执行
//foreach (var item in ProSegRunListViewItems)
//{
// var FindData = FreeSql.Select<ProgramSeg>(item.ProgramSegId)
// .IncludeMany(a => a.ProSteps,
// then => then.IncludeMany(b => b.MeterSpeeds)
// .IncludeMany(b => b.MeterCond1Temps)
// .IncludeMany(b => b.MeterCond2Temps)
// .IncludeMany(b => b.MeterCond2Presss)
// .IncludeMany(b => b.MeterEVAPExpTemps)
// .IncludeMany(b => b.MeterExPresss)
// .IncludeMany(b => b.MeterHVVols)
// .IncludeMany(b => b.MeterInhPresss)
// .IncludeMany(b => b.MeterInhTemps)
// .IncludeMany(b => b.MeterLubePresss)
// .IncludeMany(b => b.MeterLVVols)
// .IncludeMany(b => b.MeterOCRs)
// .IncludeMany(b => b.MeterOS1Temps)
// .IncludeMany(b => b.MeterOS2Temps)
// .IncludeMany(b => b.MeterPTCEntTemps)
// .IncludeMany(b => b.MeterPTCFlows)
// .IncludeMany(b => b.MeterPTCPws)
// .IncludeMany(b => b.MeterEnvRHs)
// .IncludeMany(b => b.MeterEnvTemps)
// ).ToList().FirstOrDefault();
//防止上一次下载的程序多余当前的步骤,为了清空多余的步骤数据,增加一行的数据
ReturnPlcParsData = ProParsSongZhiHelper.AddNullData(ReturnPlcParsData);
//装载PLC地址
ReturnPlcParsData = ProParsSongZhiHelper.LoadPlcCellAddress(ReturnPlcParsData);
// if (FindData != null && FindData.ProSteps != null && FindData.ProSteps.Any())
// {
// //执行程序的步骤集合数据
// ReturnPlcParsData = ProParsSongZhiHelper.GetPlcParsData(FindData.ProSteps, FindData.ProRepeat);
// //把次数给PLC那么此时应该是最后一个程序给PLC了
// ProParsSongZhiHelper.LoadProCycleToPlc(MachineRtDataService.SiemensDrive, FindData.ProRepeat);
// }
//}
ProParsSongZhiHelper.LoadDataToPLC(MachineRtDataService.SiemensDrive, ReturnPlcParsData);
////防止上一次下载的程序多余当前的步骤,为了清空多余的步骤数据,增加一行的数据
//ReturnPlcParsData = ProParsSongZhiHelper.AddNullData(ReturnPlcParsData);
////装载PLC地址
//ReturnPlcParsData = ProParsSongZhiHelper.LoadPlcCellAddress(ReturnPlcParsData);
//ProParsSongZhiHelper.LoadDataToPLC(MachineRtDataService.SiemensDrive, ReturnPlcParsData);
//下载完成的话,则标记状态
SysRunService.MachineRunState1.IsProLoad = true;