alielie
2025-03-23 40014e6e41f1ec017a07b7a620b3c700807d0519
Plugin.ServoManage/ServoManage.xaml.cs
@@ -1,39 +1,724 @@
using HMI.Base;
using HMI.Core.Setting;
using HMI.Core.Util;
using HMI.ParameterManage.Entity;
using HMI.ParameterManage.Util;
using HMI.UI.Util;
using Plugin.ServoManage.Entity;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.Threading;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Plugin.ServoManage
{
    [AttributeUsage(AttributeTargets.Property)]
    public class IsStatusAttribute : Attribute
    {
    }
    /// <summary>
    /// UserControl1.xaml 的交互逻辑
    /// </summary>
    public partial class ServoManage: UserControl
    public partial class ServoManage : PluginControl
    {
        public static string FilePath { get; private set; }
        public static string ProductFilePath { get; private set; }
        private ObservableCollection<ServoData> servos;
        public ObservableCollection<ServoData> 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<ServoProductData> servoProducts;
        public ObservableCollection<ServoProductData> ServoProducts
        {
            get => servoProducts;
            set
            {
                Set(ref servoProducts, value);
            }
        }
        /// <summary>
        /// 实例化服务器接口函数
        /// </summary>
        private OpcInterface.OpcInterface lTSCADAApi = new OpcInterface.OpcInterface();
        private bool isActived = false;
        private System.Timers.Timer motorMonitorTimer;
        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);
            }
        }
        public ServoManage()
        {
            DataContext = this;
            motorMonitorTimer = new System.Timers.Timer();
            motorMonitorTimer.Elapsed += MotorMonitorTimer_Elapsed;
            InitializeComponent();
        }
        private void MotorMonitorTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            this.motorMonitorTimer.Enabled = false;
            try
            {
                RefreshServoStatus();
                this.motorMonitorTimer.Enabled = true;
            }
            catch (Exception ex)
            {
                this.motorMonitorTimer.Enabled = true;
                return;
            }
        }
        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))
                        {
                            this.motorMonitorTimer.Interval = 100;
                            this.motorMonitorTimer.Start();
                            isActived = true;
                        }
                        else
                        {
                            MsgBoxHelper2.Error(errMsg);
                        }
                    }
                    else
                    {
                        isActived = true;
                    }
                }
                catch (Exception ex)
                {
                    log.Error("Active Failed.", ex);
                    MsgBoxHelper2.Error(ex.Message);
                }
            }
        }
        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<ServoData> data = new ObservableCollection<ServoData>();
                if (File.Exists(FilePath))
                {
                    data = XmlHelper.DeserializeFromXml<ObservableCollection<ServoData>>(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<ServoProductData> ReadCommonProducts()
        {
            ObservableCollection<ServoProductData> datas = new ObservableCollection<ServoProductData>();
            List<ProductData> products = ParameterManager.GetProducts<List<ProductData>>();
            if (products != null && products.Count > 0)
            {
                foreach (var product in products)
                {
                    var parameter = ParameterManager.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<ServoProductData> datas = new ObservableCollection<ServoProductData>();
                //if (File.Exists(FilePath))
                //{
                //    datas = XmlHelper.DeserializeFromXml<ObservableCollection<ServoProductData>>(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()
        {
            Dispatcher.Invoke(() =>
            {
                if (SelectedServo == null) return;
                PropertyInfo[] properties = this.GetType().GetProperties();
                foreach (var prop in properties)
                {
                    if (!Attribute.IsDefined(prop, typeof(IsStatusAttribute)))
                    {
                        continue;
                    }
                    if (prop.Name == "SelectedProduct")
                    {
                        var data = GetBitValue($"{SelectedServo.Name}_sRecipeCode");
                        SelectedProduct = data;
                    }
                    else
                    {
                        var data = GetBitValue($"{SelectedServo.Name}_{prop.Name}");
                        prop.SetValue(this, data);
                    }
                }
            });
        }
        /// <summary>
        /// 设置DB地址bool值
        /// </summary>
        /// <param name="subbuttonX">子按钮</param>
        /// <param name="address">地址</param>
        /// <param name="bol">值</param>
        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);
            }
        }
        /// <summary>
        /// 通过当前标签读取值
        /// </summary>
        /// <param name="tag">标签</param>
        /// <returns>返回值</returns>
        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
            {
                motorMonitorTimer.Enabled = false;
                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
            {
                motorMonitorTimer.Enabled = true;
            }
        }
        private void DoSignClick(string tag)
        {
            if (!string.IsNullOrEmpty(tag))
            {
                SetBitValue($"{SelectedServo?.Name}_{tag}", "true");
                Thread.Sleep(50);
                SetBitValue($"{SelectedServo?.Name}_{tag}", "false");
            }
        }
        /// <summary>
        /// 使能/断使能 按钮
        /// </summary>
        /// <param name="btnName"></param>
        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());
            }
        }
    }
}