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 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 OpcInterface.OpcInterface lTSCADAApi = new OpcInterface.OpcInterface();
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;
}
}
}
}