using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using Aitex.Core.RT.Log; using Aitex.Core.UI.MVVM; using Aitex.Core.Util; using Aitex.Core.Utilities; using MECF.Framework.Common.DataCenter; using MECF.Framework.Common.OperationCenter; using OpenSEMI.ClientBase; using OpenSEMI.Ctrlib.Controls; using Virgo_D.UI.Config; using VirgoCommon; namespace VirgoUI.Client.Models.Sys { public class ModuleUiViewModelBase : UiViewModelBase { public string SystemName { get; set; } public override void SubscribeKeys() { SubscribeKeys(this, SystemName); } public override void UpdateSubscribe(Dictionary data, object target, string module = null) { Parallel.ForEach(target.GetType().GetProperties().Where(_hasSubscriptionAttribute), property => { PropertyInfo pi = (PropertyInfo)property; SubscriptionAttribute subscription = property.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = module == null ? $"{SystemName}.{subscription.ModuleKey}" : string.Format("{0}.{1}", module, subscription.ModuleKey); if (_subscribedKeys.Contains(key) && data.ContainsKey(key)) { try { var convertedValue = Convert.ChangeType(data[key], pi.PropertyType); var originValue = Convert.ChangeType(pi.GetValue(target, null), pi.PropertyType); if (originValue != convertedValue) { pi.SetValue(target, convertedValue, null); } } catch (Exception ex) { LOG.Error("由RT返回的数据更新失败" + key, ex); } } }); Parallel.ForEach(target.GetType().GetFields().Where(_hasSubscriptionAttribute), property => { FieldInfo pi = (FieldInfo)property; SubscriptionAttribute subscription = property.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = module == null ? $"{SystemName}.{subscription.ModuleKey}" : string.Format("{0}.{1}", module, subscription.ModuleKey); if (_subscribedKeys.Contains(key) && data.ContainsKey(key)) { try { var convertedValue = Convert.ChangeType(data[key], pi.FieldType); pi.SetValue(target, convertedValue); } catch (Exception ex) { LOG.Error("由RT返回的数据更新失败" + key, ex); } } }); } public void InvokePropertyChanged(string propertyName) { NotifyOfPropertyChange(propertyName); } public void InvokeAllPropertyChanged() { PropertyInfo[] ps = this.GetType().GetProperties(); foreach (PropertyInfo p in ps) { InvokePropertyChanged(p.Name); if (p.PropertyType == typeof(ICommand)) { DelegateCommand cmd = p.GetValue(this, null) as DelegateCommand; if (cmd != null) cmd.RaiseCanExecuteChanged(); } } FieldInfo[] fi = this.GetType().GetFields(); foreach (FieldInfo p in fi) { InvokePropertyChanged(p.Name); if (p.FieldType == typeof(ICommand)) { DelegateCommand cmd = p.GetValue(this) as DelegateCommand; if (cmd != null) cmd.RaiseCanExecuteChanged(); } } //Parallel.ForEach(this.GetType().GetProperties(), property => InvokePropertyChanged(property.Name)); } protected override void InvokePropertyChanged() { PropertyInfo[] ps = this.GetType().GetProperties(); foreach (PropertyInfo p in ps) { if (!p.GetCustomAttributes(false).Any(attribute => attribute is IgnorePropertyChangeAttribute)) InvokePropertyChanged(p.Name); if (p.PropertyType == typeof(ICommand)) { if (p.GetValue(this, null) is IDelegateCommand cmd) cmd.RaiseCanExecuteChanged(); } } FieldInfo[] fi = this.GetType().GetFields(); foreach (FieldInfo p in fi) { InvokePropertyChanged(p.Name); if (p.FieldType == typeof(ICommand)) { DelegateCommand cmd = p.GetValue(this) as DelegateCommand; if (cmd != null) cmd.RaiseCanExecuteChanged(); } } //Parallel.ForEach(this.GetType().GetProperties(), property => InvokePropertyChanged(property.Name)); } } public class UiViewModelBase : BaseModel { private PeriodicJob _timer; protected ConcurrentBag _subscribedKeys = new ConcurrentBag(); protected Func _isSubscriptionAttribute; protected Func _hasSubscriptionAttribute; [IgnorePropertyChange] public List> _allDataItemsA = new List>(); [IgnorePropertyChange] public List> _allDataItemsB = new List>(); #region Property public ModuleInfo FOUPA { get; set; } public ModuleInfo FOUPB { get; set; } public ModuleInfo EFEM { get; set; } public ModuleInfo Aligner1 { get; set; } public ModuleInfo Aligner2 { get; set; } public ModuleInfo Cooling1 { get; set; } public ModuleInfo Cooling2 { get; set; } public ModuleInfo PMA { get; set; } public ModuleInfo PMB { get; set; } #region Wafer info for machine public WaferInfo PMAWafer { get; set; } public WaferInfo PMBWafer { get; set; } public WaferInfo Aligner1Wafer { get; set; } public WaferInfo Aligner2Wafer { get; set; } public WaferInfo Cooling1Wafer { get; set; } public WaferInfo Cooling2Wafer { get; set; } public WaferInfo EfemRobotWafer1 { get; set; } public WaferInfo EfemRobotWafer2 { get; set; } public Dictionary ModuleTemperature { get; set; } #endregion Wafer info for machine public ICommand DeviceOperationCommand { get; protected set; } #endregion Property protected override void OnInitialize() { base.OnInitialize(); PageEnabled = true; DeviceOperationCommand = new DelegateCommand(DeviceOperation); ModuleTemperature = new Dictionary(); SubscribeKeys(); } void DeviceOperation(object param) { InvokeClient.Instance.Service.DoOperation(RtOperation.DeviceOperation.ToString(), (object[])param); } protected void InitModules() { EFEM = ModuleManager.ModuleInfos["EfemRobot"]; if (ModuleManager.ModuleInfos.ContainsKey("EfemRobot")) { EfemRobotWafer1 = ModuleManager.ModuleInfos["EfemRobot"].WaferManager.Wafers[0]; EfemRobotWafer2 = ModuleManager.ModuleInfos["EfemRobot"].WaferManager.Wafers[1]; } Aligner1 = ModuleManager.ModuleInfos["Aligner1"]; if (ModuleManager.ModuleInfos.ContainsKey("Aligner1")) Aligner1Wafer = ModuleManager.ModuleInfos["Aligner1"].WaferManager.Wafers[0]; Aligner2 = ModuleManager.ModuleInfos["Aligner2"]; if (ModuleManager.ModuleInfos.ContainsKey("Aligner2")) Aligner2Wafer = ModuleManager.ModuleInfos["Aligner2"].WaferManager.Wafers[0]; Cooling1 = ModuleManager.ModuleInfos["Cooling1"]; if (ModuleManager.ModuleInfos.ContainsKey("Cooling1")) Cooling1Wafer = ModuleManager.ModuleInfos["Cooling1"].WaferManager.Wafers[0]; Cooling2 = ModuleManager.ModuleInfos["Cooling2"]; if (ModuleManager.ModuleInfos.ContainsKey("Cooling2")) Cooling2Wafer = ModuleManager.ModuleInfos["Cooling2"].WaferManager.Wafers[0]; FOUPA = ModuleManager.ModuleInfos["LP1"]; FOUPB = ModuleManager.ModuleInfos["LP2"]; if (ModuleManager.ModuleInfos.ContainsKey("PMA")) { PMA = ModuleManager.ModuleInfos["PMA"]; PMAWafer = ModuleManager.ModuleInfos["PMA"].WaferManager.Wafers[0]; } if (ModuleManager.ModuleInfos.ContainsKey("PMB")) { PMB = ModuleManager.ModuleInfos["PMB"]; PMBWafer = ModuleManager.ModuleInfos["PMB"].WaferManager.Wafers[0]; } } public string GetUnitStatusBackground(string status) { if (status != null) status = status.Trim().ToLower(); switch (status) { case "error": return "red"; case "idle": return "Transparent"; case "init": return "Yellow"; default: return "LawnGreen"; } } /// /// support wafer transfer for slot /// public void OnWaferTransfer(DragDropEventArgs args) { try { float temp = 0.0f; if (ModuleTemperature.ContainsKey(args.TranferTo.ModuleID)) { temp = ModuleTemperature[args.TranferTo.ModuleID]; } WaferMoveManager.Instance.TransferWafer(args.TranferFrom, args.TranferTo, temp); } catch (Exception ex) { LOG.Write(ex); } } /// /// support context menu /// public void OnMouseUp(object sender, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Right) { Slot slot = sender as Slot; ContextMenu cm = ContextMenuManager.Instance.GetSlotMenus(slot); if (cm != null) { ((FrameworkElement)e.Source).ContextMenu = cm; } } } public UiViewModelBase() { _timer = new PeriodicJob(1000, this.OnTimer, "UIUpdaterThread - " + GetType().Name); _isSubscriptionAttribute = attribute => attribute is SubscriptionAttribute; _hasSubscriptionAttribute = mi => mi.GetCustomAttributes(false).Any(_isSubscriptionAttribute); _allDataItemsA = SystemConfigManager.Instance.GetMonitorDataList("A"); _allDataItemsB = SystemConfigManager.Instance.GetMonitorDataList("B"); } public virtual void SubscribeKeys() { SubscribeKeys(this); } // protected virtual bool OnTimer() { try { Poll(); } catch (Exception ex) { LOG.Error(ex.Message); } return true; } public virtual void EnableTimer(bool enable) { if (enable) _timer.Start(); else _timer.Pause(); } protected virtual void Poll() { if (_subscribedKeys.Count > 0) { Dictionary result = QueryDataClient.Instance.Service.PollData(_subscribedKeys); if (result == null) { LOG.Error("获取RT数据失败"); return; } if (result.Count != _subscribedKeys.Count) { string unknowKeys = string.Empty; foreach (string key in _subscribedKeys) { if (!result.ContainsKey(key)) { unknowKeys += key + "\r\n"; } } //System.Diagnostics.Debug.Assert(false, unknowKeys); } InvokeBeforeUpdateProperty(result); UpdateValue(result); Application.Current.Dispatcher.Invoke(new Action(() => { InvokePropertyChanged(); InvokeAfterUpdateProperty(result); })); } } protected virtual void InvokePropertyChanged() { Refresh(); } protected virtual void InvokeBeforeUpdateProperty(Dictionary data) { } protected virtual void InvokeAfterUpdateProperty(Dictionary data) { } public Dictionary> GetDataElements(string culture, string type, string chamber) { Dictionary> result = new Dictionary>(); Dictionary> all = GetDataElements(type); foreach (var tuple in all) { if (!string.IsNullOrEmpty(chamber)) { if (!tuple.Key.StartsWith($"{chamber}.") && !tuple.Key.StartsWith($"IO32.{chamber}.")) continue; } result.Add(tuple.Key, Tuple.Create(tuple.Value.Item1, culture == CultureSupported.Chinese ? tuple.Value.Item3 : tuple.Value.Item2, tuple.Value.Item4)); } return result; } public Dictionary> GetDataElements(string type) { Dictionary> dicItems = new Dictionary>(); if (type == "A") { foreach (var dataItem in _allDataItemsA) { dicItems[dataItem.Item1] = dataItem; } } else { foreach (var dataItem in _allDataItemsB) { dicItems[dataItem.Item1] = dataItem; } } return dicItems; } void UpdateGasItem(bool enable, string display, string id, string key, Dictionary> dicItems) { if (enable && dicItems.ContainsKey(key)) { dicItems[key] = Tuple.Create(key, dicItems[key].Item2.Replace(id, display), dicItems[key].Item3.Replace(id, display), dicItems[key].Item4); } else { dicItems.Remove(key); } } void UpdateValue(Dictionary data) { if (data == null) return; UpdateSubscribe(data, this); var properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.GetCustomAttribute() != null); foreach (var property in properties) { var moduleAttr = property.GetCustomAttribute(); UpdateSubscribe(data, property.GetValue(this), moduleAttr.Module); } } protected void Subscribe(string key) { if (!string.IsNullOrEmpty(key)) { _subscribedKeys.Add(key); } } public void SubscribeKeys(UiViewModelBase target) { SubscribeKeys(target, ""); } public void SubscribeKeys(UiViewModelBase target, string module) { Parallel.ForEach(target.GetType().GetProperties().Where(_hasSubscriptionAttribute), property => { SubscriptionAttribute subscription = property.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = subscription.ModuleKey; if (!string.IsNullOrEmpty(module)) { key = $"{module}.{key}"; subscription.SetModule(module); } if (!_subscribedKeys.Contains(key)) _subscribedKeys.Add(key); }); Parallel.ForEach(target.GetType().GetFields().Where(_hasSubscriptionAttribute), method => { SubscriptionAttribute subscription = method.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = subscription.ModuleKey; if (!string.IsNullOrEmpty(module)) { key = $"{module}.{key}"; subscription.SetModule(module); } if (!_subscribedKeys.Contains(key)) _subscribedKeys.Add(key); }); } public virtual void UpdateSubscribe(Dictionary data, object target, string module = null) { Parallel.ForEach(target.GetType().GetProperties().Where(_hasSubscriptionAttribute), property => { PropertyInfo pi = (PropertyInfo)property; SubscriptionAttribute subscription = property.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = subscription.ModuleKey; key = module == null ? key : string.Format("{0}.{1}", module, key); if (_subscribedKeys.Contains(key) && data.ContainsKey(key)) { try { var convertedValue = Convert.ChangeType(data[key], pi.PropertyType); var originValue = Convert.ChangeType(pi.GetValue(target, null), pi.PropertyType); if (originValue != convertedValue) { pi.SetValue(target, convertedValue, null); } } catch (Exception ex) { LOG.Error("由RT返回的数据更新失败" + key, ex); } } }); Parallel.ForEach(target.GetType().GetFields().Where(_hasSubscriptionAttribute), property => { FieldInfo pi = (FieldInfo)property; SubscriptionAttribute subscription = property.GetCustomAttributes(false).First(_isSubscriptionAttribute) as SubscriptionAttribute; string key = subscription.ModuleKey; if (_subscribedKeys.Contains(key) && data.ContainsKey(key)) { try { var convertedValue = Convert.ChangeType(data[key], pi.FieldType); pi.SetValue(target, convertedValue); } catch (Exception ex) { LOG.Error("由RT返回的数据更新失败" + key, ex); } } }); } protected override void OnActivate() { base.OnActivate(); EnableTimer(true); } protected override void OnDeactivate(bool close) { base.OnDeactivate(close); EnableTimer(false); } } }