ProcessDetailViewModel.cs 69 KB

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