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
|
{
|
}
|
|
/// <summary>
|
/// UserControl1.xaml 的交互逻辑
|
/// </summary>
|
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 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<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 = ProductManager.GetProducts<List<ProductData>>();
|
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<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()
|
{
|
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;
|
}
|
}
|
|
/// <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
|
{
|
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");
|
}
|
}
|
|
/// <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());
|
}
|
}
|
|
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;
|
}
|
}
|
}
|
}
|