using ConnectionUtil; using HMI.Base; using HMI.Core.Entity; using HMI.Core.Manager; using HMI.Core.Setting; using HMI.Core.Util; using HMI.UI; using HMI.UI.Util; using OPCConnection; using Plugin.ServoManage.Entity; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Reflection; using System.Threading; using System.Timers; using System.Windows; using System.Windows.Controls; using System.Windows.Threading; namespace Plugin.ServoManage { [AttributeUsage(AttributeTargets.Property)] public class IsStatusAttribute : Attribute { } /// /// UserControl1.xaml 的交互逻辑 /// public partial class ServoManage : PluginControl { public static string FilePath { get; private set; } public static string ProductFilePath { get; private set; } private ObservableCollection servos; public ObservableCollection Servos { get => servos; set { Set(ref servos, value); } } private ServoData selectedServo; public ServoData SelectedServo { get => selectedServo; set { Set(ref selectedServo, value); Set("HasSelectedServo"); RefreshServoStatus(); } } public bool HasSelectedServo { get => SelectedServo != null; } private string selectedProduct; [IsStatus] public string SelectedProduct { get => selectedProduct; set { if (value != selectedProduct) { Set(ref selectedProduct, value); if (SelectedServo != null) { SetBitValue($"{SelectedServo.Name}_sRecipeCode", value); } } } } private ObservableCollection servoProducts; public ObservableCollection ServoProducts { get => servoProducts; set { Set(ref servoProducts, value); } } /// /// 实例化服务器接口函数 /// private SCADAApi lTSCADAApi = new OPCClient(); private bool isActived = false; private System.Timers.Timer motorMonitorTimer; #region ServoData private string enable; [IsStatus] public string Enable { get => enable; set { Set(ref enable, value); } } private string currentPosition; [IsStatus] public string CurrentPosition { get => $"{currentPosition}{SelectedServo?.Unit}"; set { Set(ref currentPosition, value); } } private string currentSpeed; [IsStatus] public string CurrentSpeed { get => $"{currentSpeed}{SelectedServo?.Unit}/s"; set { Set(ref currentSpeed, value); } } private string overAcc; [IsStatus] public string OverAcc { get => $"{overAcc}{SelectedServo?.Unit}/s²"; set { Set(ref overAcc, value); } } private string overDec; [IsStatus] public string OverDec { get => $"{overDec}{SelectedServo?.Unit}/s²"; set { Set(ref overDec, value); } } private string hmiPosition; [IsStatus] public string HMIPosition { get => $"{hmiPosition}{SelectedServo?.Unit}"; set { Set(ref hmiPosition, value); } } private string hmiSpeed; [IsStatus] public string HMISpeed { get => $"{hmiSpeed}{SelectedServo?.Unit}/s"; set { Set(ref hmiSpeed, value); } } private string jogVelocity; [IsStatus] public string JogVelocity { get => $"{jogVelocity}%"; set { Set(ref jogVelocity, value); } } private string inchDistance; [IsStatus] public string InchDistance { get => $"{inchDistance}{SelectedServo?.Unit}"; set { Set(ref inchDistance, value); } } private string dir; [IsStatus] public string Dir { get => dir; set { Set(ref dir, value); } } private string alarmCode = "0"; [IsStatus] public string AlarmCode { get => alarmCode; set { Set(ref alarmCode, value); } } private string warnCode = "0"; [IsStatus] public string WarnCode { get => warnCode; set { Set(ref warnCode, value); } } private string faultCode = "0"; [IsStatus] public string FaultCode { get => faultCode; set { Set(ref faultCode, value); } } private string positiveLimit; [IsStatus] public string PositiveLimit { get => positiveLimit; set { Set(ref positiveLimit, value); } } private string homeSwitch; [IsStatus] public string HomeSwitch { get => homeSwitch; set { Set(ref homeSwitch, value); } } private string negativeLimit; [IsStatus] public string NegativeLimit { get => negativeLimit; set { Set(ref negativeLimit, value); } } private string axisEnabled; [IsStatus] public string AxisEnabled { get => axisEnabled; set { Set(ref axisEnabled, value); } } private string readyOK; [IsStatus] public string ReadyOK { get => readyOK; set { Set(ref readyOK, value); } } private string running; [IsStatus] public string Running { get => running; set { Set(ref running, value); } } private string homed; [IsStatus] public string Homed { get => homed; set { Set(ref homed, value); } } private string axisError; [IsStatus] public string AxisError { get => axisError; set { Set(ref axisError, value); } } private string axisWarn; [IsStatus] public string AxisWarn { get => axisWarn; set { Set(ref axisWarn, value); } } private string posCode = "0"; [IsStatus] public string PosCode { get => posCode; set { Set(ref posCode, value); } } #endregion public ServoManage() { DataContext = this; motorMonitorTimer = new System.Timers.Timer(); motorMonitorTimer.Elapsed += MotorMonitorTimer_Elapsed; motorMonitorTimer.Interval = 100; InitializeComponent(); } private void MotorMonitorTimer_Elapsed(object sender, ElapsedEventArgs e) { RefreshServoStatus(); } public override void SetBaseFolder(string folder) { FilePath = Path.Combine(folder, "Servo.data"); ProductFilePath = Path.Combine(folder, "ServoProduct.data"); base.SetBaseFolder(folder); } public override void Active() { base.Active(); if (!isActived) { try { if (SystemSetting.Instance.PlcEnabled) { if (lTSCADAApi.Connect2("127.0.0.1", 6543, 18888, out string errMsg)) { motorMonitorTimer.Enabled = true; isActived = true; } else { MsgBoxHelper2.Error(errMsg); } } else { isActived = true; } } catch (Exception ex) { log.Error("Active Failed.", ex); MsgBoxHelper2.Error(ex.Message); } } else { motorMonitorTimer.Enabled = true; } } public override void DeActive() { motorMonitorTimer.Enabled = false; base.DeActive(); } private void UserControl_Loaded(object sender, RoutedEventArgs e) { LoadData(); LoadProductData(); this.Loaded -= UserControl_Loaded; } private void Button_Click(object sender, RoutedEventArgs e) { Button btn = sender as Button; ServoData data = btn.DataContext as ServoData; switch (btn.Name) { case "addServoBtn": OpenServoModal(null); break; case "editServoBtn": OpenServoModal(data); break; case "delServoBtn": TryDeleteServo(data); break; case "rfhServoBtn": LoadData(); break; case "addProductBtn": OpenProductModal(null); break; default: break; } } #region Servo private void LoadData() { try { ObservableCollection data = new ObservableCollection(); if (File.Exists(FilePath)) { data = XmlHelper.DeserializeFromXml>(FilePath); } Servos = data; } catch (Exception ex) { log.Error("Load Servo Data Failed.", ex); ToastHelper.Error(this.lang("App.LoadFailed")); } } private void OpenServoModal(ServoData data) { bool isUpdate = data != null; try { ServoModal modal = new ServoModal { Title = isUpdate ? this.lang("App.Edit") : this.lang("App.Add"), Owner = Window.GetWindow(this) }; if (modal.Open(data ?? new ServoData(), Servos) == true) { LoadData(); } } catch (Exception ex) { log.Error($"Add Or Edit Data Failed.", ex); var title = isUpdate ? this.lang("App.EditFailed") : this.lang("App.AddFailed"); MsgBoxHelper2.Error($"{title}: {ex.Message}"); } } private void TryDeleteServo(ServoData data) { try { if (MsgBoxHelper2.WarnChoose(this.lang("HMI.MakeSureDeleteSingle", data.Name)) == MessageBoxResult.OK) { int index = Servos.IndexOf(data); if (index > 0) { var temp = XmlHelper.DeepClone(Servos); temp.RemoveAt(index); XmlHelper.SerializeToXml(FilePath, temp); } LoadData(); } } catch (Exception ex) { log.Error($"Delete Servo Failed.", ex); MsgBoxHelper2.Error($"{this.lang("App.DeleteFailed")}: {ex.Message}"); } } #endregion #region product public ObservableCollection ReadCommonProducts() { ObservableCollection datas = new ObservableCollection(); List products = ProductManager.GetProducts>(); if (products != null && products.Count > 0) { foreach (var product in products) { var parameter = ProductManager.GetParametersByProductName(product.Name) ?.FirstOrDefault(p => p.Name == "ProgramCode"); if (parameter != null) { datas.Add(new ServoProductData { Model = product.Name, ProgramCode = parameter.Value, }); } } } return datas; } private void LoadProductData() { try { //ObservableCollection datas = new ObservableCollection(); //if (File.Exists(FilePath)) //{ // datas = XmlHelper.DeserializeFromXml>(ProductFilePath); //} ServoProducts = ReadCommonProducts(); } catch (Exception ex) { log.Error("Load Servo Product Data Failed.", ex); ToastHelper.Error(this.lang("App.LoadFailed")); } } private void OpenProductModal(ServoProductData data) { bool isUpdate = data != null; try { ServoProductModal modal = new ServoProductModal { Title = isUpdate ? this.lang("App.Edit") : this.lang("App.Add"), Owner = Window.GetWindow(this) }; if (modal.Open(data ?? new ServoProductData(), ServoProducts) == true) { LoadProductData(); } } catch (Exception ex) { log.Error($"Add Or Edit Product Data Failed.", ex); var title = isUpdate ? this.lang("App.EditFailed") : this.lang("App.AddFailed"); MsgBoxHelper2.Error($"{title}: {ex.Message}"); } } #endregion private void RefreshServoStatus() { this.motorMonitorTimer.Enabled = false; try { if (SelectedServo == null) return; PropertyInfo[] properties = this.GetType().GetProperties(); foreach (var prop in properties) { if (!Attribute.IsDefined(prop, typeof(IsStatusAttribute))) { continue; } Dispatcher.InvokeAsync(new Action(() => { if (prop.Name == "SelectedProduct") { var data = GetBitValue($"{SelectedServo.Name}_sRecipeCode"); SelectedProduct = data; } else { var data = GetBitValue($"{SelectedServo.Name}_{prop.Name}"); prop.SetValue(this, data); } }), DispatcherPriority.SystemIdle); } } catch (Exception ex) { } finally { this.motorMonitorTimer.Enabled = true; } } /// /// 设置DB地址bool值 /// /// 子按钮 /// 地址 /// 值 private void SetBitValue(string tag, string val) { if (!lTSCADAApi.DoFctWriteSingle(tag, val, out string errMsg)) { log.Error($"Set Bit Value Failed.{errMsg}"); MsgBoxHelper2.Error(errMsg); } } /// /// 通过当前标签读取值 /// /// 标签 /// 返回值 private string GetBitValue(string tag) { if (lTSCADAApi.DoFctReadSingle(tag, out string res, out string err)) { return res; } else { return ""; } } private void Servo_Click(object sender, RoutedEventArgs e) { if (SelectedServo == null) { ToastHelper.Warning(this.lang("svo.selectAServo")); return; } Button btn = sender as Button; try { switch (btn.Tag) { case "Enable": EnableDoClick(btn.Tag.ToString()); break; case "Dir": EnableDoClick(btn.Tag.ToString()); break; default: //DoSignClick(btn.Tag?.ToString()); break; } } catch (Exception ex) { log.Error($"Servo Opt Failed, BtnName is {btn.Name}", ex); MsgBoxHelper2.Error(ex.Message); } finally { } } private void DoSignClick(string tag) { if (!string.IsNullOrEmpty(tag)) { SetBitValue($"{SelectedServo?.Name}_{tag}", "true"); Thread.Sleep(50); SetBitValue($"{SelectedServo?.Name}_{tag}", "false"); } } /// /// 使能/断使能 按钮 /// /// private void EnableDoClick(string btnName) { bool val = GetBitValue($"{SelectedServo?.Name}_{btnName}") == "1"; SetBitValue($"{SelectedServo?.Name}_{btnName}", $"{(!val ? 1 : 0)}"); } private void Label_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (SelectedServo == null) { ToastHelper.Warning(this.lang("svo.selectAServo")); return; } Label label = sender as Label; var tag = label.Tag.ToString(); NumberPanel np = new NumberPanel() { Title = this.lang($"svo.{tag}"), Owner = Window.GetWindow(this) }; string value = label.Content.ToString(); if (value.Contains("%")) { value = value.Replace("%", ""); } else if (SelectedServo != null) { value = value.Split(new string[] { SelectedServo.Unit }, StringSplitOptions.None)[0]; } if (np.Open(value) == true) { SetBitValue($"{SelectedServo?.Name}_{tag}", np.Data?.ToString()); } } private void Button_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { Button btn = sender as Button; var tag = btn.Tag.ToString(); try { motorMonitorTimer.Enabled = false; SetBitValue($"{SelectedServo?.Name}_{tag}", "true"); } finally { motorMonitorTimer.Enabled = true; } } private void Button_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) { Button btn = sender as Button; var tag = btn.Tag.ToString(); try { motorMonitorTimer.Enabled = false; SetBitValue($"{SelectedServo?.Name}_{tag}", "false"); } finally { motorMonitorTimer.Enabled = true; } } } }