using CommunityToolkit.Mvvm.Input; using FLY.FilmCasting.AutoDie.Common; using FLY.FilmCasting.AutoDie.IService; using FLY.Thick.Base.UI; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using Unity; namespace FLY.FilmCasting.AutoDie.UI.Client { /// <summary> /// Page_Setup.xaml 的交互逻辑 /// </summary> public partial class PgSetup : Page { PgSetupVm viewModel; public PgSetup() { InitializeComponent(); } [InjectionMethod] public void Init( IUnityContainer container, IFeedbackHeatService feedback, IHeatBufService heatBuf, IHeatCellService heatCell) { viewModel = new PgSetupVm(); viewModel.Init(container, feedback, heatBuf, heatCell); this.DataContext = viewModel; } } public class PgSetupVm : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; #region 参数 public double ThresholdHeatSigma { get; set; } public int Step { get; set; } public bool HasCheckFilmVelocity { get; set; } public bool HasCheck { get; set; } public int Delay { get; set; } public int ThresholdSigmaMax { get; set; } public int StableRange { get; set; } public int[] HeatEffectCurve { get; set; } public bool IsForbidUpDown { get; set; } public double CtrlLine { get; set; } public double Kp { get; set; } /// <summary> /// 对位模式, 加热与厚度相关性阀值, 相关性 >=0.7 /// </summary> public double ThresholdR { get; set; } /// <summary> /// 最大功率 /// </summary> public int MaxHeat { get; set; } = 100; /// <summary> /// 偏移量界面的显示范围 /// </summary> public int RangeOfOffset { get; set; } = 50; /// <summary> /// 中心偏厚 单位 % /// </summary> public double CenterTarget { get; set; } /// <summary> /// 基础加热 单位 % /// </summary> public int BaseHeat { get; set; } = 15; /// <summary> /// 混合数 /// </summary> public int Mix { get; set; } /// <summary> /// 膜距离 /// </summary> public double FilmLength { get; set; } = 20; /// <summary> /// 分级控制 /// </summary> public ObservableCollection<LvCtrlLine> LvCtrlLines { get; } = new ObservableCollection<LvCtrlLine>(); #endregion #region Command public RelayCommand SmoothCmd { get; } public RelayCommand ApplyCmd { get; } #endregion public IFeedbackHeatService Feedback { get; private set; } public IHeatBufService HeatBuf { get; private set; } public IHeatCellService HeatCell { get; private set; } IUnityContainer container; public PgSetupVm() { SmoothCmd = new RelayCommand(() => { HeatCell.ThresholdHeatSigma = this.ThresholdHeatSigma; HeatCell.Smooth(); }); ApplyCmd = new RelayCommand(Apply); } [InjectionMethod] public void Init( IUnityContainer container, IFeedbackHeatService feedback, IHeatBufService heatBuf, IHeatCellService heatCell) { this.container = container; this.Feedback = feedback; this.HeatBuf = heatBuf; this.HeatCell = heatCell; //参数绑定 #region 参数 Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.ThresholdHeatSigma), this, nameof(ThresholdHeatSigma)); Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.IsForbidUpDown), this, nameof(IsForbidUpDown)); Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.CtrlLine), this, nameof(CtrlLine)); Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.Kp), this, nameof(Kp)); Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.MaxHeat), this, nameof(MaxHeat)); Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.RangeOfOffset), this, nameof(RangeOfOffset)); Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.CenterTarget), this, nameof(CenterTarget)); Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.LvCtrlLines), () => { LvCtrlLines.Clear(); if (this.HeatCell.LvCtrlLines == null) return; if (this.HeatCell.LvCtrlLines.Count() == 0) return; foreach (var lvCtrlLine in this.HeatCell.LvCtrlLines) { LvCtrlLines.Add(new LvCtrlLine() { CtrlLine = lvCtrlLine.CtrlLine, Mix = lvCtrlLine.Mix }); } }); Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.Mix), this, nameof(Mix)); Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.BaseHeat), this, nameof(BaseHeat)); Misc.BindingOperations.SetBinding(this.Feedback, nameof(IFeedbackHeatService.Step), this, nameof(Step)); Misc.BindingOperations.SetBinding(this.Feedback, nameof(IFeedbackHeatService.HasCheck), this, nameof(HasCheck)); Misc.BindingOperations.SetBinding(this.Feedback, nameof(IFeedbackHeatService.Delay), this, nameof(Delay)); Misc.BindingOperations.SetBinding(this.Feedback, nameof(IFeedbackHeatService.HasCheckFilmVelocity), this, nameof(HasCheckFilmVelocity)); Misc.BindingOperations.SetBinding(this.Feedback, nameof(IFeedbackHeatService.FilmLength), this, nameof(FilmLength)); Misc.BindingOperations.SetBinding(this.HeatBuf, nameof(IHeatBufService.ThresholdSigmaMax), this, nameof(ThresholdSigmaMax)); Misc.BindingOperations.SetBinding(this.HeatBuf, nameof(IHeatBufService.StableRange), this, nameof(StableRange)); Misc.BindingOperations.SetBinding(this.HeatBuf, nameof(IHeatBufService.HeatEffectCurve), () => { if (this.HeatBuf.HeatEffectCurve != null) HeatEffectCurve = (int[])this.HeatBuf.HeatEffectCurve.Clone(); else HeatEffectCurve = null; }); Misc.BindingOperations.SetBinding(this.HeatBuf, nameof(IHeatBufService.ThresholdR), this, nameof(ThresholdR)); #endregion } bool CheckValid_HeatEffectCurve() { int[] list = HeatEffectCurve; if ((list == null) || (list.Count() == 0)) { FLY.ControlLibrary.Window_WarningTip.Show( "参数异常", "加热效果为空", TimeSpan.FromSeconds(2)); return false; } int cnt = list.Count(); if ((int)(cnt / 2) * 2 == cnt) { FLY.ControlLibrary.Window_WarningTip.Show( "参数异常", "加热效果格式出错,应该如2,5,8,5,2", TimeSpan.FromSeconds(2)); return false; } for (int i = 0; i < list.Count() / 2; i++) { int idx0 = i; int idx_0 = list.Count() - 1 - idx0; if (list[idx0] != list[idx_0]) { FLY.ControlLibrary.Window_WarningTip.Show( "参数异常", "加热效果格式出错,应该如2,5,8,5,2", TimeSpan.FromSeconds(2)); return false; } int idx1 = idx0 + 1; if (list[idx0] > list[idx1]) { FLY.ControlLibrary.Window_WarningTip.Show( "参数异常", "加热效果格式出错,应该如2,5,8,5,2", TimeSpan.FromSeconds(2)); return false; } } return true; } bool CheckValid_LvCtrlLines() { for (int i = 0; i < LvCtrlLines.Count(); i++) { var lvCtrlLine = LvCtrlLines[i]; if (lvCtrlLine.CtrlLine >= CtrlLine) { FLY.ControlLibrary.Window_WarningTip.Show( "参数异常", "多级控制 的每级控制线 必须小于 基本控制线", TimeSpan.FromSeconds(2)); return false; } if (lvCtrlLine.Mix <= Mix) { FLY.ControlLibrary.Window_WarningTip.Show( "参数异常", "多级控制 的每级厚度混合数 必须大于 基本厚度混合数", TimeSpan.FromSeconds(2)); return false; } if (i + 1 < LvCtrlLines.Count()) { var lvCtrlLine1 = LvCtrlLines[i + 1]; if (lvCtrlLine.CtrlLine <= lvCtrlLine1.CtrlLine) { FLY.ControlLibrary.Window_WarningTip.Show( "参数异常", "多级控制 的每级控制线 必须 从大到小排列", TimeSpan.FromSeconds(2)); return false; } if (lvCtrlLine.Mix >= lvCtrlLine1.Mix) { FLY.ControlLibrary.Window_WarningTip.Show( "参数异常", "多级控制 的每级混合数 必须 从小到大排列", TimeSpan.FromSeconds(2)); return false; } } } return true; } bool CheckValid() { if (CheckValid_HeatEffectCurve() == false) return false; if (CheckValid_LvCtrlLines() == false) return false; if (Mix < 2) { FLY.ControlLibrary.Window_WarningTip.Show( "参数异常", "混合数<2", TimeSpan.FromSeconds(2)); return false; } if (FilmLength < 2) { FLY.ControlLibrary.Window_WarningTip.Show( "参数异常", "模头到测厚仪距离<2m", TimeSpan.FromSeconds(2)); return false; } if (BaseHeat < 0 || BaseHeat > 50) { FLY.ControlLibrary.Window_WarningTip.Show( "参数异常", "基础加热不能小于0% 或者大于 50%", TimeSpan.FromSeconds(2)); return false; } return true; } private void Apply() { if (!WdPassword.Authorize("AutoDie")) return; if (!CheckValid()) return; //参数设置 HeatCell.ThresholdHeatSigma = this.ThresholdHeatSigma; HeatCell.IsForbidUpDown = this.IsForbidUpDown; HeatCell.CtrlLine = Math.Round(this.CtrlLine, 1); HeatCell.Kp = this.Kp; HeatCell.MaxHeat = this.MaxHeat; HeatCell.RangeOfOffset = this.RangeOfOffset; HeatCell.CenterTarget = Math.Round(this.CenterTarget, 1); HeatCell.BaseHeat = this.BaseHeat; if (LvCtrlLines.Count() > 0) { var lvCtrlLines = new LvCtrlLine[LvCtrlLines.Count()]; for (int i = 0; i < LvCtrlLines.Count(); i++) { var lvCtrlLine = LvCtrlLines[i]; lvCtrlLines[i] = new LvCtrlLine() { CtrlLine = lvCtrlLine.CtrlLine, Mix = lvCtrlLine.Mix }; } HeatCell.LvCtrlLines = lvCtrlLines; } else { HeatCell.LvCtrlLines = null; } HeatCell.Mix = Mix; Feedback.Step = this.Step; Feedback.HasCheckFilmVelocity = this.HasCheckFilmVelocity; Feedback.HasCheck = this.HasCheck; Feedback.Delay = this.Delay; Feedback.FilmLength = FilmLength; HeatBuf.ThresholdSigmaMax = this.ThresholdSigmaMax; HeatBuf.StableRange = this.StableRange; HeatBuf.HeatEffectCurve = this.HeatEffectCurve; HeatBuf.ThresholdR = this.ThresholdR; HeatCell.Apply(); HeatBuf.Apply(); Feedback.Apply(); FLY.ControlLibrary.Window_Tip.Show("参数设置", "成功", TimeSpan.FromSeconds(2)); } } public class PgSetupVmUt : PgSetupVm { public PgSetupVmUt() { ThresholdHeatSigma = 7; Step = 5; HasCheckFilmVelocity = true; HasCheck = true; Delay = 60; ThresholdSigmaMax = 4; StableRange = 4; HeatEffectCurve = new int[] { 2, 3, 7, 3, 2 }; IsForbidUpDown = true; CtrlLine = 5; Kp = 0.8; ThresholdR = 0.7; MaxHeat = 50; RangeOfOffset = 30; CenterTarget = 2; Mix = 3; FilmLength = 12; LvCtrlLines.Add(new LvCtrlLine() { CtrlLine = 3, Mix = 6 }); LvCtrlLines.Add(new LvCtrlLine() { CtrlLine = 1, Mix = 100 }); } } public class HeatEffectConverter : IValueConverter { #region IValueConverter 成员 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var list = value as int[]; if (list == null) { return null; } string str = ""; for (int i = 0; i < list.Count(); i++) { if (i == 0) str += list[i].ToString(); else str += "," + list[i].ToString(); } return str; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string str = value as string; if (string.IsNullOrEmpty(str)) { //不合法 return null; } string[] ss = str.Split(','); List<int> list = new List<int>(); for (int i = 0; i < ss.Length; i++) { int num; if (int.TryParse(ss[i], out num)) { list.Add(num); } } return list.ToArray(); } #endregion } public class TimeSpan2SecondConverter : IValueConverter { #region IValueConverter 成员 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (!(value is TimeSpan)) return null; TimeSpan ts = (TimeSpan)value; return (int)(ts.TotalSeconds); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return null; } #endregion } public class StableConverter : IValueConverter { #region IValueConverter 成员 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { STABILITY stable = (STABILITY)value; switch (stable) { case STABILITY.IDLE: return "等待"; case STABILITY.ERROR_NO_ARRIVE: return "等待:加热点还没到达测厚仪"; case STABILITY.ERROR_SIGMA_OVERSIZE: return "等待:2σ太大 "; case STABILITY.ERROR_PARAM_CHANGED: return "等待:膜宽变化大于100mm"; case STABILITY.ERROR_THICK_CHANGED: return "等待:厚度均值波动大"; case STABILITY.ERROR_CORREL: return "等待:相关性不够"; case STABILITY.OK_CORREL: return "稳定:相关性高"; default: return "???"; } } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return null; } #endregion } public class MaxR2VisConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (!(value is double)) return null; double maxR = (double)value; if (maxR < 0) { return Visibility.Collapsed; } else { return Visibility.Visible; } } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } public class Id2VisConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (!(value is long)) return null; long id = (long)value; if (id < 0) { return Visibility.Collapsed; } else { return Visibility.Visible; } } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } }