ProcessDetailViewModel.cs 66 KB

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