ProcessDetailViewModel.cs 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522
  1. using Aitex.Core.RT.Log;
  2. using Aitex.Core.UI.ControlDataContext;
  3. using Aitex.Core.Util;
  4. using Caliburn.Micro;
  5. using Caliburn.Micro.Core;
  6. using MECF.Framework.Common.CommonData;
  7. using MECF.Framework.Common.ControlDataContext;
  8. using MECF.Framework.Common.DataCenter;
  9. using MECF.Framework.Common.Utilities;
  10. using MECF.Framework.UI.Client.CenterViews.Configs.SystemConfig;
  11. using MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory;
  12. using MECF.Framework.UI.Client.CenterViews.Dialogs;
  13. using MECF.Framework.UI.Client.ClientBase;
  14. using OpenSEMI.ClientBase;
  15. using SciChart.Charting.Visuals;
  16. using SciChart.Charting.Visuals.Annotations;
  17. using SciChart.Charting.Visuals.Axes;
  18. using SciChart.Charting.Visuals.RenderableSeries;
  19. using SciChart.Data.Model;
  20. using System;
  21. using System.Collections.Concurrent;
  22. using System.Collections.Generic;
  23. using System.Collections.ObjectModel;
  24. using System.Data;
  25. using System.Diagnostics;
  26. using System.Drawing;
  27. using System.Linq;
  28. using System.Threading;
  29. using System.Threading.Tasks;
  30. using System.Windows;
  31. using Action = System.Action;
  32. using Media = System.Windows.Media;
  33. using System.Windows.Controls;
  34. using SciChart.Charting.Model.ChartData;
  35. using MECF.Framework.UI.Client.Converter;
  36. using MECF.Framework.UI.Client.CenterViews.Operations.RealTime;
  37. namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
  38. {
  39. public class StepInfo
  40. {
  41. public DateTime StartTime { get; set; }
  42. public DateTime StepEndTime { get; set; }
  43. public DateTime EndTime { get; set; }
  44. public string StepNo { get; set; }
  45. public string StepName { get; set; }
  46. public double StepTime { get; set; }
  47. public bool IsChecked { get; set; } = true;
  48. public string SubRecipeStepNumber { get; set; }
  49. public string SubRecipeStepName { get; set; }
  50. public string SubRecipeStepTime { get; set; }
  51. public string SubRecipeLoopInfo { get; set; }
  52. public string TempCorrection { get; set; }
  53. public string TempPid { get; set; }
  54. }
  55. public class ProcessDetailViewModel<T> : ModuleUiViewModelBase where T : IComparable
  56. {
  57. public class TimeChartDataLine : ChartDataLine<T>
  58. {
  59. public string Module { get; set; }
  60. public DateTime StartTime { get; set; }
  61. public DateTime EndTime { get; set; }
  62. public TimeChartDataLine(string dataName, string module, DateTime startTime, DateTime endTime) : base(dataName)
  63. {
  64. StartTime = startTime;
  65. EndTime = endTime;
  66. Module = module;
  67. }
  68. }
  69. public class QueryIndexer
  70. {
  71. public TimeChartDataLine DataLine { get; set; }
  72. public List<string> DataList { get; set; }
  73. public DateTime TimeToken { get; set; }
  74. }
  75. public bool IsPermission { get => this.Permission == 3; }
  76. private byte _directionByte = 0x03;
  77. private ProcessDetailView view;
  78. /// <summary>
  79. /// 正在导出数据事件。
  80. /// </summary>
  81. private event EventHandler Exporting;
  82. private CancellationTokenSource _cancellationTokenSource;
  83. #region Property
  84. private const int MAX_PARAMETERS = 20;
  85. private Queue<Color> colorQueue = new Queue<Color>(new Color[]{Color.Red,Color.Orange,Color.Yellow,Color.Green,Color.Blue,Color.Pink,Color.Purple,Color.Aqua,Color.Bisque,Color.Brown,Color.BurlyWood,Color.CadetBlue,
  86. Color.CornflowerBlue,Color.DarkBlue,Color.DarkCyan,Color.DarkGray,Color.DarkGreen,Color.DarkKhaki,Color.DarkMagenta,Color.DarkOliveGreen, Color.DarkOrange,
  87. Color.DarkSeaGreen,Color.DarkSlateBlue,Color.DarkSlateGray,Color.DarkViolet,Color.DeepPink,Color.DeepSkyBlue,Color.DimGray, Color.DodgerBlue,Color.ForestGreen, Color.Gold,
  88. Color.Gray,Color.GreenYellow,Color.HotPink,Color.Indigo,Color.Khaki,Color.LightBlue,Color.LightCoral,Color.LightGreen, Color.LightPink,Color.LightSalmon,Color.LightSkyBlue,
  89. Color.LightSlateGray,Color.LightSteelBlue,Color.LimeGreen,Color.MediumOrchid,Color.MediumPurple,Color.MediumSeaGreen,Color.MediumSlateBlue,Color.MediumSpringGreen,
  90. Color.MediumTurquoise,Color.Moccasin,Color.NavajoWhite,Color.Olive,Color.OliveDrab,Color.OrangeRed,Color.Orchid,Color.PaleGoldenrod,Color.PaleGreen,
  91. Color.PeachPuff,Color.Peru,Color.Plum,Color.PowderBlue,Color.RosyBrown,Color.RoyalBlue,Color.SaddleBrown,Color.Salmon,Color.SeaGreen, Color.Sienna,
  92. Color.SkyBlue,Color.SlateBlue,Color.SlateGray,Color.SpringGreen,Color.Teal,Color.Aquamarine,Color.Tomato,Color.Turquoise,Color.Violet,Color.Wheat, Color.YellowGreen});
  93. private ObservableCollection<ParameterNode> _ParameterNodes;
  94. public ObservableCollection<ParameterNode> ParameterNodes
  95. {
  96. get { return _ParameterNodes; }
  97. set { _ParameterNodes = value; NotifyOfPropertyChange("ParameterNodes"); }
  98. }
  99. public List<ParameterNode> DoubleParameterNodes { get; set; } = new List<ParameterNode>();
  100. public ObservableCollection<IRenderableSeries> SelectedData { get; set; }
  101. public ObservableCollection<IRenderableSeries> SynSelectedData { get; set; }
  102. public List<ProcessHistoryLot> RecipeDatas { get; set; }
  103. private static object _lockSelection = new object();
  104. private AutoRange _autoRange;
  105. public AutoRange ChartAutoRange
  106. {
  107. get { return _autoRange; }
  108. set
  109. {
  110. _autoRange = value;
  111. NotifyOfPropertyChange(nameof(ChartAutoRange));
  112. }
  113. }
  114. private IRange _timeRange;
  115. public IRange VisibleRangeTime
  116. {
  117. get { return _timeRange; }
  118. set
  119. {
  120. _timeRange = value;
  121. NotifyOfPropertyChange(nameof(VisibleRangeTime));
  122. }
  123. }
  124. private IRange _VisibleRangeValue;
  125. public IRange VisibleRangeValue
  126. {
  127. get { return _VisibleRangeValue; }
  128. set { _VisibleRangeValue = value; NotifyOfPropertyChange(nameof(VisibleRangeValue)); }
  129. }
  130. private PeriodicJob _thread;
  131. private ConcurrentBag<QueryIndexer> _lstTokenTimeData = new ConcurrentBag<QueryIndexer>();
  132. private Dictionary<string, string> _processDetailDisplayDic = new Dictionary<string, string>();
  133. private string _resolution;
  134. private AnnotationCollection _annotations;
  135. public AnnotationCollection Annotations
  136. {
  137. get => _annotations;
  138. set
  139. {
  140. _annotations = value;
  141. InvokePropertyChanged(nameof(Annotations));
  142. }
  143. }
  144. //StartTime,EndTime,StepNo,StepName
  145. private List<StepInfo> _stepInfo = new List<StepInfo>();
  146. public List<StepInfo> StepInfo
  147. {
  148. get { return _stepInfo; }
  149. set { _stepInfo = value; this.NotifyOfPropertyChange(nameof(StepInfo)); }
  150. }
  151. public bool IsStepVisiable => RecipeDatas.Count == 1;
  152. public DateTime StepStartTime { get; set; }
  153. public DateTime StepEndTime { get; set; }
  154. private bool _isAdding;
  155. private string _stepName;
  156. public string StepNameDisPlay
  157. {
  158. get { return _stepName; }
  159. set
  160. {
  161. if (_stepName != value)
  162. {
  163. _stepName = value;
  164. NotifyOfPropertyChange(nameof(StepNameDisPlay));
  165. }
  166. }
  167. }
  168. private string _recipeNameDisPlay;
  169. public string RecipeNameDisPlay
  170. {
  171. get { return _recipeNameDisPlay; }
  172. set
  173. {
  174. if (_recipeNameDisPlay != value)
  175. {
  176. _recipeNameDisPlay = value;
  177. NotifyOfPropertyChange(nameof(RecipeNameDisPlay));
  178. }
  179. }
  180. }
  181. private DateTime _pointTime;
  182. public DateTime PointTime
  183. {
  184. get { return _pointTime; }
  185. set
  186. {
  187. if (_pointTime != value)
  188. {
  189. _pointTime = value;
  190. NotifyOfPropertyChange(nameof(PointTime));
  191. }
  192. }
  193. }
  194. private double _lastPointX;
  195. private string _direction = "XYDirection";
  196. public string Direction
  197. {
  198. get { return _direction; }
  199. set
  200. {
  201. if (value != _direction)
  202. {
  203. _direction = value;
  204. if (_direction == "XDirection") _directionByte = 1;
  205. else if (_direction == "YDirection") _directionByte = 2;
  206. else if (_direction == "XYDirection") _directionByte = 3;
  207. NotifyOfPropertyChange(nameof(Direction));
  208. }
  209. }
  210. }
  211. //public Tuple<DateTime,double> _timePairs;
  212. private MultiLineXAxisLabelProvider _mulitiLineLabel;
  213. public MultiLineXAxisLabelProvider MultiLineLabel
  214. {
  215. get { return _mulitiLineLabel; }
  216. set
  217. {
  218. if (_mulitiLineLabel != value)
  219. {
  220. _mulitiLineLabel = value;
  221. NotifyOfPropertyChange(nameof(MultiLineLabel));
  222. }
  223. }
  224. }
  225. private double _xScale = 1;
  226. public double XScale
  227. {
  228. get { return _xScale; }
  229. set
  230. {
  231. if (_xScale != value)
  232. {
  233. _xScale = value;
  234. NotifyOfPropertyChange(nameof(XScale));
  235. }
  236. }
  237. }
  238. private double _yScale = 0.1;
  239. public double YScale
  240. {
  241. get { return _yScale; }
  242. set
  243. {
  244. if (value != _yScale)
  245. {
  246. _yScale = value;
  247. NotifyOfPropertyChange(nameof(YScale));
  248. }
  249. }
  250. }
  251. #endregion
  252. private RealtimeProvider _realtimeProvider;
  253. #region Function
  254. public ProcessDetailViewModel(List<ProcessHistoryLot> recipes)
  255. {
  256. _realtimeProvider = new RealtimeProvider();
  257. DisplayName = "Process Detail";
  258. RecipeDatas = recipes;
  259. ParameterNodes = _realtimeProvider.GetParameters(out var dict);
  260. DoubleParameterNodes = _realtimeProvider.GetParameters(out dict).ToList();
  261. for (int j = 0; j < ParameterNodes.Count; j++)
  262. {
  263. ParameterNodes[j].IsVisibilityParentNode = Visibility.Hidden;
  264. DoubleParameterNodes[j].IsVisibilityParentNode = Visibility.Hidden;
  265. }
  266. _processDetailDisplayDic = dict;
  267. if (recipes == null || recipes.Count == 0)
  268. {
  269. return;
  270. }
  271. SelectedData = new ObservableCollection<IRenderableSeries>();
  272. SynSelectedData = new ObservableCollection<IRenderableSeries>();
  273. VisibleRangeValue = new DoubleRange(0, 10);
  274. // Annotations = new AnnotationCollection();
  275. _thread = new PeriodicJob(200, MonitorData, "ProcessDetail", true);
  276. try
  277. {
  278. RecipeDatas.ToList().ForEach(recipe =>
  279. {
  280. QueryStep(recipe.StartTime, recipe.EndTime);
  281. });
  282. if (StepInfo != null && StepInfo.Count > 0)
  283. {
  284. StepStartTime = StepInfo.FirstOrDefault().StartTime;
  285. StepEndTime = StepInfo.LastOrDefault().EndTime;
  286. }
  287. MultiLineLabel = new MultiLineXAxisLabelProvider(StepStartTime);
  288. }
  289. catch (Exception ex)
  290. {
  291. LOG.Info(ex.StackTrace + ":" + ex.Message);
  292. }
  293. }
  294. protected override void OnViewLoaded(object view)
  295. {
  296. base.OnViewLoaded(view);
  297. this.view = (ProcessDetailView)view;
  298. }
  299. protected override void OnActivate()
  300. {
  301. _resolution = "f1";
  302. if (QueryDataClient.Instance.Service.GetConfig($"System.DataHistoryResolution") != null)
  303. _resolution = $"f{QueryDataClient.Instance.Service.GetConfig($"System.DataHistoryResolution")}";
  304. base.OnActivate();
  305. }
  306. public void QueryStep(DateTime starTime, DateTime endTime)//, string recipeName去掉查询recipeName名称,有嵌套调用
  307. {
  308. starTime = starTime.AddMinutes(-1);
  309. endTime = endTime.AddMinutes(1);
  310. string sql = $"SELECT * FROM \"process_data\" where (\"process_begin_time\" >= '{starTime:yyyy/MM/dd HH:mm:ss.fff}' and \"process_end_time\" <= '{endTime:yyyy/MM/dd HH:mm:ss.fff}') order by \"process_begin_time\" DESC;";
  311. DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql);
  312. if (dbData != null && dbData.Rows.Count > 0)
  313. {
  314. List<ProcessDataLot> ProcessDataLotList = new List<ProcessDataLot>();
  315. for (int i = 0; i < dbData.Rows.Count; i++)
  316. {
  317. ProcessDataLot item = new ProcessDataLot();
  318. item.GUID = dbData.Rows[i]["guid"].ToString();
  319. item.RecipeName = dbData.Rows[i]["recipe_name"].ToString().Trim('\\');
  320. item.ProcessStatus = dbData.Rows[i]["process_status"].ToString();
  321. item.WaferDataGUID = dbData.Rows[i]["wafer_data_guid"].ToString();
  322. item.ProcessIn = dbData.Rows[i]["process_in"].ToString();
  323. if (!dbData.Rows[i]["process_begin_time"].Equals(DBNull.Value))
  324. {
  325. item.ProcessBeginTime = (DateTime)dbData.Rows[i]["process_begin_time"];
  326. }
  327. if (!dbData.Rows[i]["process_end_time"].Equals(DBNull.Value))
  328. {
  329. item.ProcessEndTime = (DateTime)dbData.Rows[i]["process_end_time"];
  330. }
  331. ProcessDataLotList.Add(item);
  332. }
  333. //Annotations.Add(VerLine(Media.Brushes.Blue, ProcessDataLotList[0].ProcessBeginTime, Media.Brushes.Blue, $"{ProcessDataLotList[0].RecipeName}"));
  334. //Annotations.Add(VerLine(Media.Brushes.Blue, ProcessDataLotList[0].ProcessEndTime, Media.Brushes.Blue, $"Recipe End"));
  335. string sql2 = $"SELECT * FROM \"recipe_step_data\" where";
  336. sql2 += $" \"recipe_step_data\".\"process_data_guid\" = '{ProcessDataLotList[0].GUID.ToString()}'";
  337. sql2 += " order by \"step_begin_time\" ASC;";
  338. using (var table = QueryDataClient.Instance.Service.QueryData(sql2))
  339. {
  340. if (!(table == null || table.Rows.Count == 0))
  341. {
  342. for (int i = 0; i < table.Rows.Count; i++)
  343. {
  344. var item = table.Rows[i];
  345. DateTime StartTime = DateTime.MinValue;
  346. DateTime EndTime = DateTime.MinValue;
  347. double stepTime = 0;
  348. if (!item["step_begin_time"].Equals(DBNull.Value))
  349. StartTime = (DateTime)item["step_begin_time"];
  350. if (!item["step_end_time"].Equals(DBNull.Value))
  351. EndTime = (DateTime)item["step_end_time"];
  352. if (!item["step_time"].Equals(DBNull.Value))
  353. {
  354. stepTime = (float)item["step_time"];
  355. }
  356. string stepNo = item["step_number"].ToString();
  357. string stepName = item["step_name"].ToString();
  358. if (StartTime > DateTime.MinValue && EndTime > DateTime.MinValue)
  359. {
  360. var time = StartTime.AddSeconds(stepTime);
  361. if (EndTime < time && time < ProcessDataLotList[0].ProcessEndTime)//解决process过程abort,数据导出。
  362. {
  363. EndTime = StartTime.AddSeconds(stepTime);
  364. }
  365. else
  366. {
  367. if (_stepInfo.Any())//临时处理表中recipe_step_data step_end_time数据不能真实反映步次结束时间的问题
  368. {
  369. int lastIndex = _stepInfo.Count - 1;
  370. if (_stepInfo[lastIndex].EndTime > StartTime) _stepInfo[lastIndex].EndTime = StartTime;
  371. }
  372. _stepInfo.Add(new StepInfo() { StartTime = StartTime, EndTime = EndTime, StepName = stepName, StepTime = stepTime, StepNo = stepNo });
  373. }
  374. }
  375. }
  376. }
  377. }
  378. }
  379. }
  380. public static VerticalLineAnnotation VerLine(Media.Brush stroke, DateTime x, Media.Brush color, string text)
  381. {
  382. var label = new AnnotationLabel()
  383. {
  384. LabelPlacement = LabelPlacement.TopRight,
  385. FontSize = 12,
  386. RotationAngle = 0,
  387. Foreground = color,
  388. Text = text
  389. };
  390. var line = new VerticalLineAnnotation()
  391. {
  392. Stroke = stroke,
  393. StrokeThickness = 1,
  394. X1 = x,
  395. IsEditable = false,
  396. VerticalAlignment = VerticalAlignment.Stretch,
  397. AnnotationLabels = new ObservableCollection<AnnotationLabel>() { label },
  398. };
  399. return line;
  400. }
  401. protected bool MonitorData()
  402. {
  403. try
  404. {
  405. if (_isAdding)
  406. return true;
  407. bool allUpdated = true;
  408. lock (_lockSelection)
  409. {
  410. foreach (var item in _lstTokenTimeData)
  411. {
  412. DateTime timeFrom = item.TimeToken;
  413. if (timeFrom >= item.DataLine.EndTime)
  414. continue;
  415. allUpdated = false;
  416. ChartAutoRange = AutoRange.Always;
  417. DateTime timeTo = timeFrom.AddMinutes(60);
  418. if (timeTo.DayOfYear > timeFrom.DayOfYear)
  419. timeTo = new DateTime(timeFrom.Year, timeFrom.Month, timeFrom.Day).AddDays(1);
  420. if (timeTo > item.DataLine.EndTime)
  421. timeTo = item.DataLine.EndTime;
  422. item.TimeToken = timeTo;
  423. GetData(item.DataList, timeFrom, timeTo, item.DataLine.Module, item.DataLine.DataSource);
  424. #region Update VisualMin、VisualMax、DataStatisticsInfo
  425. Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  426. {
  427. double min = ((DoubleRange)VisibleRangeValue).Min;
  428. double max = ((DoubleRange)VisibleRangeValue).Max;
  429. int PointCount = 0;
  430. foreach (var selectedData in SelectedData)
  431. {
  432. var seriesItem = selectedData as ChartDataLine<T>;
  433. if (seriesItem == null)
  434. continue;
  435. double sumValue = 0;
  436. double minValue = 100000;
  437. double maxValue = 0;
  438. double averageValue = 0;
  439. double stdevValue = 0;
  440. double sigma3Value = 0;
  441. var pointValueList = seriesItem.Points.Select(x => x.Item2).ToList();
  442. for (int i = 0; i < pointValueList.Count; i++)
  443. {
  444. sumValue += pointValueList[i];
  445. if (pointValueList[i] < minValue)
  446. minValue = pointValueList[i];
  447. if (pointValueList[i] > maxValue)
  448. maxValue = pointValueList[i];
  449. }
  450. averageValue = pointValueList.Count == 0 ? 0 : sumValue / pointValueList.Count;
  451. for (int i = 0; i < pointValueList.Count; i++)
  452. {
  453. stdevValue += Math.Pow(pointValueList[i] - averageValue, 2);
  454. }
  455. stdevValue = pointValueList.Count == 0 ? 0 : stdevValue / pointValueList.Count;
  456. sigma3Value = Math.Sqrt(stdevValue) * 3;
  457. (seriesItem.Tag as ParameterNode).AverageValue = averageValue.ToString("F2");
  458. (seriesItem.Tag as ParameterNode).MinValue = minValue.ToString("F2");
  459. (seriesItem.Tag as ParameterNode).MaxValue = maxValue.ToString("F2");
  460. (seriesItem.Tag as ParameterNode).Sigma3Value = sigma3Value.ToString("F2");
  461. min = minValue;
  462. if (maxValue != max)
  463. max = maxValue * 1.1;
  464. PointCount = pointValueList.Count;
  465. }
  466. VisibleRangeValue = new DoubleRange(min, max);
  467. }));
  468. #endregion
  469. }
  470. }
  471. if (allUpdated)
  472. {
  473. lock (_lockSelection)
  474. {
  475. while (_lstTokenTimeData.Count > 0)
  476. {
  477. _lstTokenTimeData.TryTake(out _);
  478. }
  479. ChartAutoRange = AutoRange.Never;
  480. }
  481. }
  482. }
  483. catch (Exception ex)
  484. {
  485. LOG.Error(ex.Message);
  486. }
  487. return true;
  488. }
  489. private void GetData(List<string> keys, DateTime from, DateTime to, string module, string dataSource)
  490. {
  491. string sql = "select time AS InternalTimeStamp";
  492. foreach (var dataKey in keys)
  493. {
  494. var dataId = _processDetailDisplayDic.ContainsKey(dataKey) ? _processDetailDisplayDic[dataKey] : dataKey;
  495. sql += "," + string.Format("\"{0}\"", dataId);
  496. }
  497. sql += string.Format(" from \"{0}\" where time > {1} and time <= {2} order by time asc",
  498. from.ToString("yyyyMMdd") + "." + module, from.Ticks, to.Ticks);
  499. DataTable dataTable = QueryDataClient.Instance.Service.QueryData(sql);
  500. Dictionary<string, List<HistoryDataItem>> historyData = new Dictionary<string, List<HistoryDataItem>>();
  501. if (dataTable == null || dataTable.Rows.Count == 0)
  502. return;
  503. DateTime dt = new DateTime();
  504. Dictionary<int, string> colName = new Dictionary<int, string>();
  505. for (int colNo = 0; colNo < dataTable.Columns.Count; colNo++)
  506. {
  507. colName.Add(colNo, dataTable.Columns[colNo].ColumnName);
  508. historyData[dataTable.Columns[colNo].ColumnName] = new List<HistoryDataItem>();
  509. }
  510. for (int rowNo = 0; rowNo < dataTable.Rows.Count; rowNo++)
  511. {
  512. var row = dataTable.Rows[rowNo];
  513. for (int i = 0; i < dataTable.Columns.Count; i++)
  514. {
  515. HistoryDataItem data = new HistoryDataItem();
  516. if (i == 0)
  517. {
  518. dt = new DateTime((long)row[i]);
  519. continue;
  520. }
  521. else
  522. {
  523. string dataId = colName[i];
  524. if (row[i] is DBNull || row[i] == null)
  525. {
  526. data.dateTime = dt;
  527. data.dbName = colName[i];
  528. data.value = 0;
  529. }
  530. else if (row[i] is bool)
  531. {
  532. data.dateTime = dt;
  533. data.dbName = colName[i];
  534. data.value = (bool)row[i] ? 1 : 0;
  535. }
  536. else
  537. {
  538. data.dateTime = dt;
  539. data.dbName = colName[i];
  540. var value = float.Parse(row[i].ToString()).ToString(_resolution);
  541. data.value = float.Parse(value);
  542. }
  543. }
  544. historyData[data.dbName].Add(data);
  545. }
  546. }
  547. Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  548. {
  549. try
  550. {
  551. FillDataToChart(SelectedData, dataSource, historyData);
  552. FillDataToChart(SynSelectedData, dataSource, historyData);
  553. RefresCharView();
  554. }
  555. catch (Exception ex)
  556. {
  557. LOG.Write(ex);
  558. }
  559. }));
  560. }
  561. void FillDataToChart(ObservableCollection<IRenderableSeries> series, string dataSource, Dictionary<string, List<HistoryDataItem>> historyData)
  562. {
  563. var items = series.Where(x => (x as ChartDataLine<T>).DataSource == dataSource);
  564. if (items == null) return;
  565. foreach (var item in items)
  566. {
  567. var seriesItem = item as ChartDataLine<T>;
  568. if (seriesItem == null)
  569. continue;
  570. foreach (var data in historyData)
  571. {
  572. var dataKey = _processDetailDisplayDic.ContainsKey(seriesItem.DataName) ? _processDetailDisplayDic[seriesItem.DataName] : seriesItem.DataName;
  573. if (data.Key != dataKey)
  574. continue;
  575. seriesItem.Capacity += data.Value.Count;
  576. //DateTime beginTime = StepStartTime;
  577. for (int i = 0; i < data.Value.Count; i++)
  578. {
  579. var historyDataItem = data.Value[i];
  580. if (typeof(T) == typeof(double))
  581. {
  582. //xData = Math.Round((historyDataItem.dateTime - beginTime).TotalMilliseconds / 1000, 0, MidpointRounding.AwayFromZero);
  583. seriesItem.Append((T)Convert.ChangeType((historyDataItem.dateTime - StepStartTime).TotalMilliseconds / 1000d, typeof(T)), historyDataItem.value);
  584. }
  585. else
  586. seriesItem.Append((T)Convert.ChangeType(historyDataItem.dateTime, typeof(T)), historyDataItem.value);
  587. }
  588. }
  589. }
  590. }
  591. /// <summary>
  592. /// 获取时间列表
  593. /// </summary>
  594. /// <param name="from"></param>
  595. /// <param name="to"></param>
  596. /// <param name="module"></param>
  597. /// <param name="dataSource"></param>
  598. private void GetData(DateTime from, DateTime to, string module = "PM1")
  599. {
  600. string sql = "select time AS InternalTimeStamp,\"PM1.RecipeTotalElapseTime\"";
  601. sql += string.Format(" from \"{0}\" where time > {1} and time <= {2} order by time limt 1",
  602. from.ToString("yyyyMMdd") + "." + module, from.Ticks, to.Ticks);
  603. DataTable dataTable = QueryDataClient.Instance.Service.QueryData(sql);
  604. Dictionary<string, List<HistoryDataItem>> historyData = new Dictionary<string, List<HistoryDataItem>>();
  605. if (dataTable == null || dataTable.Rows.Count == 0)
  606. {
  607. return;
  608. }
  609. foreach (DataRow row in dataTable.Rows)
  610. {
  611. DateTime dt = new DateTime();
  612. dt = new DateTime((long)row[0]);
  613. var elapseTime = Convert.ToDouble(row[1]);
  614. }
  615. }
  616. private void SelectedDataChanged()
  617. {
  618. foreach (var item in SelectedData)
  619. {
  620. if (item.Stroke.Equals(System.Windows.Media.Color.FromArgb(255, 0, 0, 255)))
  621. {
  622. Color drawingColor = colorQueue.Peek();
  623. item.Stroke = System.Windows.Media.Color.FromRgb(drawingColor.R, drawingColor.G, drawingColor.B);
  624. colorQueue.Enqueue(colorQueue.Dequeue());
  625. }
  626. }
  627. }
  628. public void TxtMouseLeftButtonDown(ParameterNode node, ObservableCollection<IRenderableSeries> series)
  629. {
  630. node.Selected = !node.Selected;
  631. ParameterCheck(node, series);
  632. }
  633. public void ParameterCheck(ParameterNode node, ObservableCollection<IRenderableSeries> series)
  634. {
  635. bool result = RefreshTreeStatusToChild(node, series);
  636. if (!result)
  637. {
  638. node.Selected = !node.Selected;
  639. DialogBox.ShowWarning($"The max number of parameters is {MAX_PARAMETERS}.");
  640. }
  641. else
  642. RefreshTreeStatusToParent(node);
  643. }
  644. /// <summary>
  645. /// Refresh tree node status from current to children, and add data to SelectedData
  646. /// </summary>
  647. private bool RefreshTreeStatusToChild(ParameterNode node, ObservableCollection<IRenderableSeries> SelectedData)
  648. {
  649. if (node?.ChildNodes.Count > 0)
  650. {
  651. for (int i = 0; i < node.ChildNodes.Count; i++)
  652. {
  653. ParameterNode n = node.ChildNodes[i];
  654. n.Selected = node.Selected;
  655. if (!RefreshTreeStatusToChild(n, SelectedData))
  656. {
  657. n.Selected = !n.Selected;
  658. return false;
  659. }
  660. }
  661. }
  662. else //leaf node
  663. {
  664. bool lockTaken = false;
  665. try
  666. {
  667. var item = SelectedData?.FirstOrDefault(x => (x as ChartDataLine<T>).DataName == node.Name);
  668. bool isExist = item != null;
  669. if (isExist && !node.Selected)//删除
  670. {
  671. SelectedData.Remove(item);
  672. }
  673. else
  674. {
  675. if (!isExist && node.Selected)
  676. {
  677. if (SelectedData.Count >= MAX_PARAMETERS)
  678. {
  679. return false;
  680. }
  681. Monitor.TryEnter(_lockSelection, 1000, ref lockTaken);
  682. if (lockTaken)
  683. {
  684. var dataId = _processDetailDisplayDic.ContainsKey(node.Name) ? _processDetailDisplayDic[node.Name] : node.Name;
  685. var module = dataId.Split('.').ToList()[0];
  686. _isAdding = true;
  687. foreach (var recipe in RecipeDatas)
  688. {
  689. TimeChartDataLine line;
  690. if (IsStepVisiable)
  691. line = new TimeChartDataLine(node.Name.Replace("Tube", "PM1"), module, StepStartTime, StepEndTime);
  692. else
  693. line = new TimeChartDataLine(node.Name.Replace("Tube", "PM1"), module, recipe.StartTime, recipe.EndTime);
  694. line.DataSource = $"{recipe.BatchID}.{recipe.RecipeName}";
  695. line.Tag = node;
  696. if (isExist)
  697. {
  698. line.Stroke = item.Stroke;
  699. line.IsVisible = item.IsVisible;
  700. line.ClearData();
  701. SelectedData.Remove(item);
  702. }
  703. else
  704. SelectedData.Add(line);
  705. AddToMonitor(line);
  706. }
  707. _isAdding = false;
  708. if (!isExist)
  709. SelectedDataChanged();
  710. }
  711. }
  712. }
  713. }
  714. finally
  715. {
  716. if (lockTaken)
  717. {
  718. Monitor.Exit(_lockSelection);
  719. }
  720. }
  721. }
  722. return true;
  723. }
  724. private void AddToMonitor(TimeChartDataLine line)
  725. {
  726. QueryIndexer indexer = new QueryIndexer()
  727. {
  728. DataLine = line,
  729. DataList = new List<string>() { line.DataName },
  730. TimeToken = line.StartTime,
  731. };
  732. _lstTokenTimeData.Add(indexer);
  733. }
  734. /// <summary>
  735. /// Refresh tree node status from current to parent
  736. /// </summary>
  737. /// <param name="node"></param>
  738. /// <returns></returns>
  739. private void RefreshTreeStatusToParent(ParameterNode node)
  740. {
  741. if (node.ParentNode != null)
  742. {
  743. if (node.Selected)
  744. {
  745. bool flag = true;
  746. for (int i = 0; i < node.ParentNode.ChildNodes.Count; i++)
  747. {
  748. if (!node.ParentNode.ChildNodes[i].Selected)
  749. {
  750. flag = false; //as least one child is unselected
  751. break;
  752. }
  753. }
  754. if (flag)
  755. node.ParentNode.Selected = true;
  756. }
  757. else
  758. {
  759. node.ParentNode.Selected = false;
  760. }
  761. RefreshTreeStatusToParent(node.ParentNode);
  762. }
  763. }
  764. #region Parameter Grid Control
  765. public void DeleteAll()
  766. {
  767. //uncheck all tree nodes
  768. foreach (ChartDataLine<T> cp in SelectedData)
  769. {
  770. (cp.Tag as ParameterNode).Selected = false;
  771. RefreshTreeStatusToParent(cp.Tag as ParameterNode);
  772. }
  773. SelectedData.Clear();
  774. }
  775. private void SetParameterNode(ObservableCollection<ParameterNode> nodes, bool isChecked)
  776. {
  777. foreach (ParameterNode n in nodes)
  778. {
  779. n.Selected = isChecked;
  780. SetParameterNode(n.ChildNodes, isChecked);
  781. }
  782. }
  783. public void Delete(ChartDataLine<T> cp)
  784. {
  785. if (cp != null)
  786. {
  787. if (SelectedData.Contains(cp))
  788. {
  789. //uncheck tree node
  790. (cp.Tag as ParameterNode).Selected = false;
  791. RefreshTreeStatusToParent(cp.Tag as ParameterNode);
  792. SelectedData.Remove(cp);
  793. }
  794. }
  795. }
  796. public async void ExportAll()
  797. {
  798. try
  799. {
  800. if (SelectedData.Count == 0)
  801. {
  802. MessageBox.Show($"Please select the data you want to export.", "Export", MessageBoxButton.OK,
  803. MessageBoxImage.Warning);
  804. return;
  805. }
  806. Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
  807. dlg.DefaultExt = ".xlsx"; // Default file extension
  808. dlg.Filter = "Excel数据表格文件(*.xlsx)|*.xlsx"; // Filter files by extension
  809. dlg.FileName = $"{DisplayName}_{string.Join(",", RecipeDatas.Select(x => x.RecipeName.Replace('\\', '.')).ToArray())}_{DateTime.Now:yyyyMMdd_HHmmss}";
  810. Nullable<bool> result = dlg.ShowDialog();// Show open file dialog box
  811. if (result == true) // Process open file dialog box results
  812. {
  813. Exporting?.Invoke(this, System.EventArgs.Empty);
  814. _cancellationTokenSource = new CancellationTokenSource();
  815. var sw = new Stopwatch();
  816. sw.Restart();
  817. System.Data.DataSet ds = new System.Data.DataSet();
  818. ds.Tables.Add(new System.Data.DataTable($"{DisplayName}_{DateTime.Now:yyyyMMdd_HHmmss}"));
  819. ds.Tables[0].Columns.Add("Recipe Info");
  820. ds.Tables[0].Columns[0].DataType = typeof(string);
  821. ds.Tables[0].Columns.Add("Date");
  822. ds.Tables[0].Columns[1].DataType = typeof(string);
  823. ds.Tables[0].Columns.Add("Time");
  824. ds.Tables[0].Columns[2].DataType = typeof(string);
  825. ds.Tables[0].Columns.Add("Step ID");
  826. ds.Tables[0].Columns[3].DataType = typeof(string);
  827. ds.Tables[0].Columns.Add("Step Name");
  828. ds.Tables[0].Columns[4].DataType = typeof(string);
  829. Dictionary<T, double[]> timeValue = new Dictionary<T, double[]>();
  830. await Task.Run(() =>
  831. {
  832. for (int i = 0; i < SelectedData.Count; i++)
  833. {
  834. List<Tuple<T, double>> data = (SelectedData[i] as ChartDataLine<T>).Points;
  835. foreach (var tuple in data)
  836. {
  837. if (!timeValue.ContainsKey(tuple.Item1))
  838. timeValue[tuple.Item1] = new double[SelectedData.Count];
  839. timeValue[tuple.Item1][i] = tuple.Item2;
  840. }
  841. ds.Tables[0].Columns.Add((SelectedData[i] as ChartDataLine<T>).DataName);
  842. ds.Tables[0].Columns[i + 5].DataType = typeof(double);
  843. }
  844. var recipeInfoRow = ds.Tables[0].NewRow();
  845. recipeInfoRow[0] = $"Recipe:{string.Join(",", RecipeDatas.Select(x => x.RecipeName).ToArray())}";
  846. ds.Tables[0].Rows.Add(recipeInfoRow);
  847. recipeInfoRow = ds.Tables[0].NewRow();
  848. recipeInfoRow[0] = $"Start Time";
  849. recipeInfoRow[1] = string.Join(",", RecipeDatas.Select(x => x.StartTime).ToArray());
  850. recipeInfoRow[2] = string.Join(",", RecipeDatas.Select(x => x.StartTime).ToArray());
  851. ds.Tables[0].Rows.Add(recipeInfoRow);
  852. recipeInfoRow = ds.Tables[0].NewRow();
  853. recipeInfoRow[0] = $"End Time";
  854. recipeInfoRow[1] = string.Join(",", RecipeDatas.Select(x => x.EndTime).ToArray());
  855. recipeInfoRow[2] = string.Join(",", RecipeDatas.Select(x => x.EndTime).ToArray());
  856. ds.Tables[0].Rows.Add(recipeInfoRow);
  857. QueryDataClientFromTable(ds);
  858. }, _cancellationTokenSource.Token).ContinueWith(t =>
  859. {
  860. if (t.IsCanceled || t.IsFaulted)
  861. return;
  862. });
  863. if (_cancellationTokenSource?.Token.IsCancellationRequested == true)
  864. return;
  865. if (!ExcelHelper.ExportToExcel(dlg.FileName, ds, out string reason))
  866. {
  867. MessageBox.Show($"Export failed, {reason}", "Export", MessageBoxButton.OK, MessageBoxImage.Warning);
  868. return;
  869. }
  870. MessageBox.Show($"Export succeed, file save as {dlg.FileName}", "Export", MessageBoxButton.OK, MessageBoxImage.Information);
  871. }
  872. }
  873. catch (Exception ex)
  874. {
  875. LOG.Write(ex);
  876. MessageBox.Show("Write failed," + ex.Message, "export failed", MessageBoxButton.OK, MessageBoxImage.Warning);
  877. }
  878. }
  879. public void DGSelectionChanged(object sender, EventArgs e)
  880. {
  881. var temp = (DataGrid)sender;
  882. var tempSelected = (IRenderableSeries)temp.SelectedItem;
  883. tempSelected.IsVisible = !tempSelected.IsVisible;
  884. }
  885. private void QueryDataClientFromTable(DataSet ds)
  886. {
  887. DateTime startTime = StepStartTime;
  888. DateTime endTime = StepEndTime;
  889. if (StepStartTime.Date == StepEndTime.Date)
  890. {
  891. SaveDataToTable(ds, startTime, endTime);
  892. }
  893. else
  894. {
  895. endTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, 23, 59, 59);
  896. while (endTime < StepEndTime)
  897. {
  898. SaveDataToTable(ds, startTime, endTime);
  899. startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, 0, 0, 0).AddDays(1);
  900. endTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, 23, 59, 59);
  901. }
  902. SaveDataToTable(ds, startTime, StepEndTime);
  903. }
  904. }
  905. private void SaveDataToTable(DataSet ds, DateTime startTime, DateTime endTime)
  906. {
  907. string stepID = "", stepName = "";
  908. string pmsql = "select time AS InternalTimeStamp";
  909. var pmColNames = _realtimeProvider.GetDBCol(startTime.ToString("yyyyMMdd") + "." + "PM1");
  910. List<string> keys = SelectedData.Select(x => (x as ChartDataLine<T>).DataName).ToList();
  911. DataTable pmDataTable = null;
  912. if (keys != null && keys.Count > 0)
  913. {
  914. List<string> pmList = new List<string>();
  915. foreach (var dataKey in keys)
  916. {
  917. var dataId = _processDetailDisplayDic.ContainsKey(dataKey) ? _processDetailDisplayDic[dataKey] : dataKey;
  918. var module = dataId.Split('.').ToList()[0];
  919. if (module.ToLower() == "pm1")
  920. {
  921. if (!pmColNames.Contains(dataId))
  922. {
  923. continue;
  924. }
  925. pmList.Add(dataId);
  926. pmsql += "," + string.Format("\"{0}\"", dataId);
  927. }
  928. }
  929. if (pmList.Count > 0)
  930. {
  931. pmsql += string.Format(" from \"{0}\" where time > {1} and time <= {2} order by time asc",
  932. startTime.ToString("yyyyMMdd") + "." + "PM1", startTime.Ticks, endTime.Ticks);
  933. pmDataTable = QueryDataClient.Instance.Service.QueryData(pmsql);
  934. if (pmDataTable == null)
  935. {
  936. MessageBox.Show($"Export failed, sql:{pmsql}", "Export", MessageBoxButton.OK, MessageBoxImage.Warning);
  937. return;
  938. }
  939. }
  940. }
  941. string systemsql = "select time AS InternalTimeStamp";
  942. var systemColNames = _realtimeProvider.GetDBCol(startTime.ToString("yyyyMMdd") + "." + "System");
  943. DataTable systemDataTable = null;
  944. if (keys != null && keys.Count > 0)
  945. {
  946. List<string> systemList = new List<string>();
  947. foreach (var dataKey in keys)
  948. {
  949. var dataId = _processDetailDisplayDic.ContainsKey(dataKey) ? _processDetailDisplayDic[dataKey] : dataKey;
  950. var module = dataId.Split('.').ToList()[0];
  951. if (module.ToLower() == "system")
  952. {
  953. if (!systemColNames.Contains(dataId))
  954. {
  955. continue;
  956. }
  957. systemsql += "," + string.Format("\"{0}\"", dataId);
  958. systemList.Add(dataId);
  959. }
  960. }
  961. if (systemList.Count > 0)
  962. {
  963. systemsql += string.Format(" from \"{0}\" where time > {1} and time <= {2} order by time asc",
  964. startTime.ToString("yyyyMMdd") + "." + "System", startTime.Ticks, endTime.Ticks);
  965. systemDataTable = QueryDataClient.Instance.Service.QueryData(systemsql);
  966. if (systemDataTable == null)
  967. {
  968. MessageBox.Show($"Export failed, sql:{systemsql}", "Export", MessageBoxButton.OK, MessageBoxImage.Warning);
  969. return;
  970. }
  971. }
  972. }
  973. int maxRow = 0;
  974. if ((pmDataTable == null || pmDataTable.Rows.Count == 0))
  975. {
  976. if (systemDataTable != null)
  977. {
  978. maxRow = systemDataTable.Rows.Count;
  979. }
  980. }
  981. else if ((systemDataTable == null || systemDataTable.Rows.Count == 0))
  982. {
  983. if (pmDataTable != null)
  984. {
  985. maxRow = pmDataTable.Rows.Count;
  986. }
  987. }
  988. else
  989. {
  990. maxRow = pmDataTable.Rows.Count > systemDataTable.Rows.Count ? systemDataTable.Rows.Count : pmDataTable.Rows.Count;
  991. }
  992. for (int i = 0; i < maxRow; i++)
  993. {
  994. var pmRow = pmDataTable != null ? pmDataTable.Rows[i] : null;
  995. var systemRow = systemDataTable != null ? systemDataTable.Rows[i] : null;
  996. //float timeIndex = 0;
  997. //float.TryParse(item.Key.ToString(), out timeIndex);
  998. //DateTime dateTimeKey = startTime.AddMilliseconds(timeIndex * 1000); ;// DateTime.Parse(item.Key.ToString());
  999. DateTime dateTimeKey = new DateTime(pmRow != null ? (long)pmRow[0] : (long)systemRow[0]);
  1000. var tempStepInfo = _stepInfo.FirstOrDefault(x => x.StartTime < dateTimeKey && x.EndTime > dateTimeKey);
  1001. if (tempStepInfo != null)// && dateTimeKey > _stepInfo[iIndex].StartTime
  1002. {
  1003. stepID = tempStepInfo.StepNo;
  1004. stepName = tempStepInfo.StepName;
  1005. }
  1006. var row = ds.Tables[0].NewRow();
  1007. row[1] = dateTimeKey.ToString("yyyy/MM/dd");
  1008. row[2] = dateTimeKey.ToString("HH:mm:ss:fff");
  1009. row[3] = stepID;
  1010. row[4] = stepName;
  1011. for (int j = 5; j < ds.Tables[0].Columns.Count; j++)
  1012. {
  1013. string colName = ds.Tables[0].Columns[j].ColumnName;
  1014. DataRow dataRow = null;
  1015. var dataId = _processDetailDisplayDic.ContainsKey(colName) ? _processDetailDisplayDic[colName] : colName;
  1016. var module = dataId.Split('.').ToList()[0];
  1017. int index = 0;
  1018. if (module == "PM1")
  1019. {
  1020. dataRow = pmRow;
  1021. foreach (var item in pmDataTable.Columns)
  1022. {
  1023. if (((DataColumn)item).ColumnName == dataId)
  1024. {
  1025. break;
  1026. }
  1027. index++;
  1028. }
  1029. }
  1030. else if (module == "System")
  1031. {
  1032. dataRow = systemRow;
  1033. foreach (var item in systemDataTable.Columns)
  1034. {
  1035. if (((DataColumn)item).ColumnName == dataId)
  1036. {
  1037. break;
  1038. }
  1039. index++;
  1040. }
  1041. }
  1042. if (dataRow[index] is DBNull || dataRow[index] == null)
  1043. {
  1044. row[j] = dataRow[index];
  1045. }
  1046. else if (dataRow[index] is bool)
  1047. {
  1048. row[j] = (bool)dataRow[index] ? 1 : 0;
  1049. }
  1050. else
  1051. {
  1052. var value = float.Parse(dataRow[index].ToString()).ToString(_resolution);
  1053. row[j] = float.Parse(value);
  1054. }
  1055. }
  1056. ds.Tables[0].Rows.Add(row);
  1057. }
  1058. }
  1059. public void Export(ChartDataLine<T> cp)
  1060. {
  1061. try
  1062. {
  1063. Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
  1064. dlg.DefaultExt = ".xlsx"; // Default file extension
  1065. dlg.Filter = "Excel数据表格文件(*.xlsx)|*.xlsx"; // Filter files by extension
  1066. dlg.FileName = $"{cp.DataName}_{DateTime.Now:yyyyMMdd_HHmmss}";
  1067. Nullable<bool> result = dlg.ShowDialog();// Show open file dialog box
  1068. if (result == true) // Process open file dialog box results
  1069. {
  1070. System.Data.DataSet ds = new System.Data.DataSet();
  1071. ds.Tables.Add(new System.Data.DataTable(cp.DataName));
  1072. ds.Tables[0].Columns.Add("Time");
  1073. ds.Tables[0].Columns[0].DataType = typeof(DateTime);
  1074. ds.Tables[0].Columns.Add(cp.DataName);
  1075. ds.Tables[0].Columns[1].DataType = typeof(double);
  1076. int i = 0;
  1077. foreach (var item in cp.Points)
  1078. {
  1079. var row = ds.Tables[0].NewRow();
  1080. row[0] = StepStartTime.AddSeconds(Convert.ToDouble(item.Item1));
  1081. row[1] = item.Item2;
  1082. ds.Tables[0].Rows.Add(row);
  1083. i++;
  1084. }
  1085. if (!ExcelHelper.ExportToExcel(dlg.FileName, ds, out string reason))
  1086. {
  1087. MessageBox.Show($"Export failed, {reason}", "Export", MessageBoxButton.OK, MessageBoxImage.Warning);
  1088. return;
  1089. }
  1090. MessageBox.Show($"Export succeed, file save as {dlg.FileName}", "Export", MessageBoxButton.OK, MessageBoxImage.Information);
  1091. }
  1092. }
  1093. catch (Exception ex)
  1094. {
  1095. LOG.Write(ex);
  1096. MessageBox.Show("Write failed," + ex.Message, "export failed", MessageBoxButton.OK, MessageBoxImage.Warning);
  1097. }
  1098. }
  1099. public void SelectColor(ChartDataLine<T> cp)
  1100. {
  1101. if (cp == null)
  1102. return;
  1103. var dlg = new System.Windows.Forms.ColorDialog();
  1104. if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
  1105. {
  1106. cp.Stroke = new System.Windows.Media.Color() { A = dlg.Color.A, B = dlg.Color.B, G = dlg.Color.G, R = dlg.Color.R };
  1107. }
  1108. }
  1109. public void CloseCmd()
  1110. {
  1111. ((Window)GetView()).Close();
  1112. }
  1113. #endregion
  1114. #region SciChart Move
  1115. public void RefresCharView()
  1116. {
  1117. this.view.sciChart.ZoomExtents();
  1118. }
  1119. public void ArrowClick(string direction)
  1120. {
  1121. switch (direction)
  1122. {
  1123. case "Up":
  1124. if (VisibleRangeValue is DoubleRange uprange)
  1125. {
  1126. VisibleRangeValue = new DoubleRange(uprange.Min + YScale, uprange.Max + YScale);
  1127. }
  1128. break;
  1129. case "Down":
  1130. if (VisibleRangeValue is DoubleRange downrange)
  1131. {
  1132. VisibleRangeValue = new DoubleRange(downrange.Min - YScale, downrange.Max - YScale);
  1133. }
  1134. break;
  1135. case "Left":
  1136. if (VisibleRangeTime is DoubleRange leftrange)
  1137. {
  1138. VisibleRangeTime = new DoubleRange(leftrange.Min - XScale, leftrange.Max - XScale);
  1139. }
  1140. break;
  1141. case "Right":
  1142. if (VisibleRangeTime is DoubleRange range)
  1143. {
  1144. VisibleRangeTime = new DoubleRange(range.Min + XScale, range.Max + XScale);
  1145. }
  1146. break;
  1147. }
  1148. }
  1149. public void ZoomInClick()//放大
  1150. {
  1151. double scale = 0;
  1152. if ((_directionByte & 0x01) == 1)//x
  1153. {
  1154. //LOG.Info($"A ZoomInClick.X:scale{XScale}-{VisibleRangeTime.Min}: {VisibleRangeTime.Max}");
  1155. if (VisibleRangeTime is DoubleRange range)
  1156. {
  1157. if (range.Max - range.Min <= XScale) return;
  1158. if (range.Max - range.Min > 2 * XScale) scale = XScale;
  1159. else scale = XScale / 2;
  1160. VisibleRangeTime = new DoubleRange(range.Min + scale, range.Max - scale);
  1161. //LOG.Info($"ZoomInClick.X:scale{XScale}-{VisibleRangeTime.Min}: {VisibleRangeTime.Max}");
  1162. }
  1163. }
  1164. if ((_directionByte & 0x02) == 2)//y
  1165. {
  1166. //LOG.Info($"A ZoomInClick.Y:scale{YScale}-{VisibleRangeValue.Min}: {VisibleRangeValue.Max}");
  1167. if (VisibleRangeValue is DoubleRange range)
  1168. {
  1169. if (range.Max - range.Min <= YScale) return;
  1170. if (range.Max - range.Min > 2 * XScale) scale = YScale;
  1171. else scale = YScale / 2;
  1172. VisibleRangeValue = new DoubleRange(range.Min + scale, range.Max - scale);
  1173. //LOG.Info($"ZoomInClick.Y:scale{YScale}-{VisibleRangeValue.Min}: {VisibleRangeValue.Max}");
  1174. }
  1175. }
  1176. }
  1177. public void ZoomOutClick()//缩小
  1178. {
  1179. if ((_directionByte & 0x01) == 1)//x
  1180. {
  1181. //LOG.Info($"A ZoomOutClick.X:scale{XScale}-{VisibleRangeTime.Min}: {VisibleRangeTime.Max}");
  1182. if (VisibleRangeTime is DoubleRange range)
  1183. {
  1184. VisibleRangeTime = new DoubleRange(range.Min - XScale, range.Max + XScale);
  1185. //LOG.Info($"ZoomOutClick.X:scale{XScale}-{VisibleRangeTime.Min}: {VisibleRangeTime.Max}");
  1186. }
  1187. }
  1188. if ((_directionByte & 0x02) == 2)//y
  1189. {
  1190. //LOG.Info($"A ZoomOutClick.Y:scale{YScale}-{VisibleRangeValue.Min}: {VisibleRangeValue.Max}");
  1191. if (VisibleRangeValue is DoubleRange range)
  1192. {
  1193. VisibleRangeValue = new DoubleRange(range.Min - YScale, range.Max + YScale);
  1194. // LOG.Info($"ZoomOutClick.Y:scale{YScale}-{VisibleRangeValue.Min}: {VisibleRangeValue.Max}");
  1195. }
  1196. }
  1197. }
  1198. public void SelectStep()
  1199. {
  1200. ObservableCollection<Option> Items = new ObservableCollection<Option>();
  1201. foreach (var item in StepInfo)
  1202. {
  1203. Items.Add(new Option() { Name = $"{item.StepNo} {item.StepName}", Index = int.Parse(item.StepNo) });
  1204. }
  1205. ItemsSelectDialogViewModel itemsSelectDialogView = new ItemsSelectDialogViewModel();
  1206. itemsSelectDialogView.Items = Items;
  1207. itemsSelectDialogView.ColumnsCount = Items.Count / 10 + 1;
  1208. WindowManager windowManager = IoC.Get<IWindowManager>() as WindowManager;
  1209. if ((bool)(windowManager as WindowManager)?.ShowDialogWithNoWindow(itemsSelectDialogView))
  1210. {
  1211. var startItem = StepInfo.FirstOrDefault(step => step.StepNo == Items.FirstOrDefault(x => x.IsChecked)?.Index.ToString());
  1212. var endItem = StepInfo.FirstOrDefault(step => step.StepNo == Items.LastOrDefault(x => x.IsChecked)?.Index.ToString());
  1213. if (startItem == null)
  1214. {
  1215. DialogBox.ShowError("Please select begin step!");
  1216. return;
  1217. }
  1218. if (endItem == null)
  1219. {
  1220. DialogBox.ShowError("Please select end step!");
  1221. return;
  1222. }
  1223. if (Items.Where(x => x.IsChecked).Count() > 2)
  1224. {
  1225. DialogBox.ShowError("The selected step numbers must be 1 or 2.");
  1226. return;
  1227. }
  1228. StepStartTime = startItem.StartTime;
  1229. StepEndTime = endItem.EndTime;
  1230. List<ParameterNode> allCheckNode = new List<ParameterNode>();
  1231. ParameterNodes.ToList().ForEach(x =>
  1232. {
  1233. allCheckNode.AddRange(GetAllCheckedLeafNode(x));
  1234. });
  1235. allCheckNode.ForEach(x => { ParameterCheck(x, SelectedData); });
  1236. }
  1237. }
  1238. private List<ParameterNode> GetAllCheckedLeafNode(ParameterNode parameterNode)
  1239. {
  1240. List<ParameterNode> retNodes = new List<ParameterNode>();
  1241. if (parameterNode.ChildNodes != null && parameterNode.ChildNodes.Count > 0)
  1242. {
  1243. foreach (var item in parameterNode.ChildNodes)
  1244. {
  1245. retNodes.AddRange(GetAllCheckedLeafNode(item));
  1246. }
  1247. }
  1248. else
  1249. {
  1250. if (parameterNode.Selected)
  1251. retNodes.Add(parameterNode);
  1252. }
  1253. return retNodes;
  1254. }
  1255. #endregion
  1256. #endregion
  1257. public void GetCursorPoint(IEnumerable<SeriesInfo> infos)
  1258. {
  1259. if (infos.Any())
  1260. {
  1261. var seriesinfo = infos.First();
  1262. if (seriesinfo.XValue is double xvalue && _lastPointX != xvalue)
  1263. {
  1264. _lastPointX = xvalue;
  1265. PointTime = StepStartTime.AddSeconds(xvalue);
  1266. if (PointTime == DateTime.MinValue) return;
  1267. var step = _stepInfo.Find(r => r.StartTime <= PointTime && r.EndTime >= PointTime);
  1268. if (step == null)
  1269. {
  1270. LOG.Info($"couldn't find CurrentTime:{PointTime:yyyy/MM/dd HH:mm:ss.FFF} in steps ,display last step:{StepNameDisPlay}");
  1271. }
  1272. else
  1273. {
  1274. StepNameDisPlay = $"{step.StepNo}:{step.StepName}";
  1275. //LOG.Info($"CurrentTime:{PointTime:yyyy/MM/dd HH:mm:ss.FFF} {StepNameDisPlay}");
  1276. }
  1277. var name = (seriesinfo.RenderableSeries as ChartDataLine<T>).DataSource.Split('.', '\\');
  1278. if (name.Length > 0)
  1279. {
  1280. RecipeNameDisPlay = name.Last();
  1281. }
  1282. else RecipeNameDisPlay = string.Empty;
  1283. }
  1284. }
  1285. }
  1286. public void ScaleChange(string direction, double factor)
  1287. {
  1288. double t = 0;
  1289. if (direction == "X")
  1290. {
  1291. t = Math.Floor(_xScale * factor * 10) / 10d;//只保留3位小数
  1292. if (t >= 0.1) XScale = t;
  1293. else DialogBox.ShowWarning("already min value");
  1294. }
  1295. else if (direction == "Y")
  1296. {
  1297. t = Math.Floor(_yScale * factor * 1000) / 1000d;
  1298. if (t >= 0.001) YScale = t;
  1299. else DialogBox.ShowWarning("already min value");
  1300. }
  1301. }
  1302. }
  1303. public class ProcessDataLot : NotifiableItem
  1304. {
  1305. private string _guid;
  1306. public string GUID
  1307. {
  1308. get => _guid;
  1309. set
  1310. {
  1311. _guid = value;
  1312. InvokePropertyChanged(nameof(GUID));
  1313. }
  1314. }
  1315. private DateTime _processBeginTime;
  1316. public DateTime ProcessBeginTime
  1317. {
  1318. get => _processBeginTime;
  1319. set
  1320. {
  1321. _processBeginTime = value;
  1322. InvokePropertyChanged(nameof(ProcessBeginTime));
  1323. }
  1324. }
  1325. private DateTime _processEndTime;
  1326. public DateTime ProcessEndTime
  1327. {
  1328. get => _processEndTime;
  1329. set
  1330. {
  1331. _processEndTime = value;
  1332. InvokePropertyChanged(nameof(ProcessEndTime));
  1333. }
  1334. }
  1335. private string _recipeName;
  1336. public string RecipeName
  1337. {
  1338. get => _recipeName;
  1339. set
  1340. {
  1341. _recipeName = value;
  1342. InvokePropertyChanged(nameof(RecipeName));
  1343. }
  1344. }
  1345. private string _processStatus;
  1346. public string ProcessStatus
  1347. {
  1348. get => _processStatus;
  1349. set
  1350. {
  1351. _processStatus = value;
  1352. InvokePropertyChanged(nameof(ProcessStatus));
  1353. }
  1354. }
  1355. private string _waferDataguid;
  1356. public string WaferDataGUID
  1357. {
  1358. get => _waferDataguid;
  1359. set
  1360. {
  1361. _waferDataguid = value;
  1362. InvokePropertyChanged(nameof(WaferDataGUID));
  1363. }
  1364. }
  1365. private string _processIn;
  1366. public string ProcessIn
  1367. {
  1368. get => _processIn;
  1369. set
  1370. {
  1371. _processIn = value;
  1372. InvokePropertyChanged(nameof(ProcessIn));
  1373. }
  1374. }
  1375. private int _recipeSettingTime;
  1376. public int RecipeSettingTime
  1377. {
  1378. get => _recipeSettingTime;
  1379. set
  1380. {
  1381. _recipeSettingTime = value;
  1382. InvokePropertyChanged(nameof(RecipeSettingTime));
  1383. }
  1384. }
  1385. }
  1386. }