diff options
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/ViewModels/MachineTechViewVM.cs')
| -rw-r--r-- | Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/ViewModels/MachineTechViewVM.cs | 1124 |
1 files changed, 1124 insertions, 0 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/ViewModels/MachineTechViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/ViewModels/MachineTechViewVM.cs new file mode 100644 index 000000000..6ccc1caa0 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/ViewModels/MachineTechViewVM.cs @@ -0,0 +1,1124 @@ +using GalaSoft.MvvmLight.Ioc; +using Google.Protobuf.Collections; +using Microsoft.Win32; +using RealTimeGraphEx.Controllers; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media; +using Tango.Core.Helpers; +using Tango.Editors; +using Tango.Integration.Observables; +using Tango.Integration.Observables.Enumerations; +using Tango.Integration.Operators; +using Tango.MachineStudio.Common.Notifications; +using Tango.MachineStudio.Common.StudioApplication; +using Tango.MachineStudio.Technician.Editors; +using Tango.MachineStudio.Technician.Project; +using Tango.MachineStudio.Technician.TechItems; +using Tango.PMR.Diagnostics; +using Tango.Settings; +using Tango.SharedUI; + +namespace Tango.MachineStudio.Technician.ViewModels +{ + /// <summary> + /// Represents the MachineTechView View Model. + /// </summary> + /// <seealso cref="Tango.SharedUI.ViewModel" /> + /// <seealso cref="Tango.MachineStudio.Common.StudioApplication.IShutdownListener" /> + public class MachineTechViewVM : ViewModel, IShutdownListener + { + private List<PropertyInfo> _diagnoticsDataProperties; + private Dictionary<SingleGraphItem, GraphController> _singleControllers; + private Dictionary<MultiGraphItem, GraphMultiController> _multiControllers; + private static object _elementsLock = new object(); + private String _lastTechProjectFile; + private INotificationProvider _notification; + private DateTime _lastDiagnosticsResponseUpdate; + private const int MIN_DIAGNOSTICS_UPDATE_MILI = 500; + + #region Properties + + private ObservableCollection<IElementEditor> _elements; + /// <summary> + /// Gets or sets the visual elements. + /// </summary> + public ObservableCollection<IElementEditor> Elements + { + get { return _elements; } + set { _elements = value; RaisePropertyChangedAuto(); } + } + + private ObservableCollection<TechItem> _availableTechItems; + /// <summary> + /// Gets or sets the available tech items. + /// </summary> + public ObservableCollection<TechItem> AvailableTechItems + { + get { return _availableTechItems; } + set { _availableTechItems = value; RaisePropertyChangedAuto(); } + } + + private TechItem _selectedTechItem; + /// <summary> + /// Gets or sets the selected available tech item. + /// </summary> + public TechItem SelectedTechItem + { + get { return _selectedTechItem; } + set { _selectedTechItem = value; RaisePropertyChangedAuto(); } + } + + /// <summary> + /// Gets or sets the db adapter. + /// </summary> + public ObservablesEntitiesAdapter Adapter { get; set; } + + /// <summary> + /// Gets or sets the application manager. + /// </summary> + public IStudioApplicationManager ApplicationManager { get; set; } + + private IMachineOperator _machineOperator; + /// <summary> + /// Gets or sets the machine operator. + /// </summary> + public IMachineOperator MachineOperator + { + get { return _machineOperator; } + set { _machineOperator = value; RaisePropertyChangedAuto(); } + } + + private bool _disableRendering; + /// <summary> + /// Gets or sets a value indicating whether [disable rendering]. + /// </summary> + public bool DisableRendering + { + get { return _disableRendering; } + set { _disableRendering = value; RaisePropertyChangedAuto(); OnDisableRenderingChanged(); } + } + + private bool _hideMenu; + /// <summary> + /// Gets or sets a value indicating whether [hide menu]. + /// </summary> + public bool HideMenu + { + get { return _hideMenu; } + set { _hideMenu = value; RaisePropertyChangedAuto(); } + } + + private PushDiagnosticsResponse _currentDiagnosticsResponse; + /// <summary> + /// Gets or sets the current diagnostics response. + /// </summary> + public PushDiagnosticsResponse CurrentDiagnosticsResponse + { + get { return _currentDiagnosticsResponse; } + set { _currentDiagnosticsResponse = value; RaisePropertyChanged(nameof(CurrentDiagnosticsResponse)); } + } + + private int _currentDiagnosticsResponseSize; + /// <summary> + /// Gets or sets the size of the current diagnostics response. + /// </summary> + /// <value> + /// The size of the current diagnostics response. + /// </value> + public int CurrentDiagnosticsResponseSize + { + get { return _currentDiagnosticsResponseSize; } + set { _currentDiagnosticsResponseSize = value; RaisePropertyChanged(nameof(CurrentDiagnosticsResponseSize)); } + } + + #endregion + + #region Commands + + /// <summary> + /// Gets or sets the save as project command. + /// </summary> + public RelayCommand SaveAsProjectCommand { get; set; } + + /// <summary> + /// Gets or sets the save project command. + /// </summary> + public RelayCommand SaveProjectCommand { get; set; } + + /// <summary> + /// Gets or sets the open project command. + /// </summary> + public RelayCommand OpenProjectCommand { get; set; } + + #endregion + + #region Constructors + + /// <summary> + /// Initializes a new instance of the <see cref="MachineTechViewVM"/> class. + /// </summary> + /// <param name="applicationManager">The application manager.</param> + /// <param name="notificationProvider">The notification provider.</param> + [PreferredConstructor] + public MachineTechViewVM(IStudioApplicationManager applicationManager, INotificationProvider notificationProvider) : this(applicationManager, notificationProvider, true) + { + + } + + /// <summary> + /// Initializes a new instance of the <see cref="MachineTechViewVM"/> class. + /// </summary> + /// <param name="applicationManager">The application manager.</param> + /// <param name="notificationProvider">The notification provider.</param> + /// <param name="loadLastProject">if set to <c>true</c> [load last project].</param> + public MachineTechViewVM(IStudioApplicationManager applicationManager, INotificationProvider notificationProvider, bool loadLastProject) + { + _notification = notificationProvider; + _singleControllers = new Dictionary<SingleGraphItem, GraphController>(); + _multiControllers = new Dictionary<MultiGraphItem, GraphMultiController>(); + AvailableTechItems = TechItem.GetAvailableTechItems().ToObservableCollection(); + SelectedTechItem = AvailableTechItems.FirstOrDefault(); + _diagnoticsDataProperties = typeof(PushDiagnosticsResponse).GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList(); + ApplicationManager = applicationManager; + ApplicationManager.ConnectedMachineChanged += ApplicationManager_ConnectedMachineChanged; + + Adapter = ObservablesEntitiesAdapter.Instance; + Elements = new ObservableCollection<IElementEditor>(); + + OpenProjectCommand = new RelayCommand(OpenProject); + SaveAsProjectCommand = new RelayCommand(SaveAsProject); + SaveProjectCommand = new RelayCommand(SaveProject); + + _lastTechProjectFile = SettingsManager.Default.MachineStudio.TechnicianModule.LasTechProjectFile; + + if (File.Exists(_lastTechProjectFile) && loadLastProject) + { + OpenProjectFile(_lastTechProjectFile); + } + } + + #endregion + + #region Event Handlers + + /// <summary> + /// Applications the manager connected machine changed. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="machine">The machine.</param> + private void ApplicationManager_ConnectedMachineChanged(object sender, Integration.Services.IExternalBridgeClient machine) + { + MachineOperator = machine; + + if (MachineOperator != null) + { + MachineOperator.DiagnosticsDataAvailable -= MachineOperator_DiagnosticsDataAvailable; + MachineOperator.DiagnosticsDataAvailable += MachineOperator_DiagnosticsDataAvailable; + } + } + + /// <summary> + /// Machines the operator diagnostics data available. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="response">The response.</param> + private void MachineOperator_DiagnosticsDataAvailable(object sender, PushDiagnosticsResponse response) + { + PopulateDiagnosticsData(response); + } + + #endregion + + #region Populate Diagnostics Data + + /// <summary> + /// Populates the diagnostics data to the proper elements. + /// </summary> + /// <param name="data">The data.</param> + private void PopulateDiagnosticsData(PushDiagnosticsResponse data) + { + if (DateTime.Now > _lastDiagnosticsResponseUpdate.AddMilliseconds(MIN_DIAGNOSTICS_UPDATE_MILI)) + { + CurrentDiagnosticsResponse = data; + _lastDiagnosticsResponseUpdate = DateTime.Now; + CurrentDiagnosticsResponseSize = data.CalculateSize(); + } + + lock (_elementsLock) + { + var elements = Elements.ToList(); + + foreach (var item in elements.Select(x => x.HostedElement as TechItem)) + { + if (item.GetType() == typeof(MonitorItem)) + { + MonitorItem monitorItem = item as MonitorItem; + + if (DateTime.Now > monitorItem.LastUpdateTime.AddMilliseconds(monitorItem.UpdateInterval)) + { + var prop = _diagnoticsDataProperties.SingleOrDefault(x => x.Name == monitorItem.TechMonitor.Name); + + if (prop != null) + { + monitorItem.Value = GetDataLastValue(monitorItem.TechMonitor, prop.GetValue(data)); + } + } + } + else if (item.GetType() == typeof(MeterItem)) + { + MeterItem meterItem = item as MeterItem; + + if (DateTime.Now > meterItem.LastUpdateTime.AddMilliseconds(meterItem.UpdateInterval)) + { + var prop = _diagnoticsDataProperties.SingleOrDefault(x => x.Name == meterItem.TechMonitor.Name); + + if (prop != null) + { + meterItem.Value = GetDataLastValue(meterItem.TechMonitor, prop.GetValue(data)); + } + } + } + else if (item.GetType() == typeof(SingleGraphItem)) + { + SingleGraphItem graphItem = item as SingleGraphItem; + + var prop = _diagnoticsDataProperties.SingleOrDefault(x => x.Name == graphItem.TechMonitor.Name); + + if (prop != null) + { + GraphController controller = null; + + if (_singleControllers.TryGetValue(graphItem, out controller)) + { + controller.PushData(GetDataArray(graphItem.TechMonitor, prop.GetValue(data))); + } + } + } + else if (item.GetType() == typeof(MultiGraphItem)) + { + MultiGraphItem graphItem = item as MultiGraphItem; + + var prop = _diagnoticsDataProperties.SingleOrDefault(x => x.Name == graphItem.TechMonitor.Name); + + if (prop != null) + { + GraphMultiController controller = null; + + if (_multiControllers.TryGetValue(graphItem, out controller)) + { + controller.PushData(GetDataMatrix(graphItem.TechMonitor, prop.GetValue(data))); + } + } + } + else if (item.GetType() == typeof(DigitalOutItem)) + { + DigitalOutItem digitalOutItem = item as DigitalOutItem; + + var digitalPin = data.DigitalPins.SingleOrDefault(x => x.Port == digitalOutItem.TechIo.Port); + + if (digitalPin != null) + { + digitalOutItem.EffectiveValue = digitalPin.Value; + } + } + else if (item.GetType() == typeof(DigitalInItem)) + { + DigitalInItem digitalInItem = item as DigitalInItem; + + var digitalPin = data.DigitalPins.SingleOrDefault(x => x.Port == digitalInItem.TechIo.Port); + + if (digitalPin != null) + { + digitalInItem.Value = digitalPin.Value; + } + } + } + } + } + + #endregion + + #region Private Methods + + /// <summary> + /// Gets the last data point from a protobuf repeated field. + /// </summary> + /// <param name="monitor">The monitor.</param> + /// <param name="value">The value.</param> + /// <returns></returns> + private double GetDataLastValue(TechMonitor monitor, object value) + { + if (!monitor.MultiChannel) + { + RepeatedField<double> arr = value as RepeatedField<double>; + return arr.LastOrDefault(); + } + else + { + RepeatedField<DoubleArray> arr = value as RepeatedField<DoubleArray>; + return arr.Last().Data.Last(); + } + } + + /// <summary> + /// Gets the data array from a protobuf repeated field. + /// </summary> + /// <param name="monitor">The monitor.</param> + /// <param name="value">The value.</param> + /// <returns></returns> + private List<double> GetDataArray(TechMonitor monitor, object value) + { + return (value as RepeatedField<double>).ToList(); + } + + /// <summary> + /// Gets the data matrix from a protobuf repeated field of <see cref="DoubleArray"/>. + /// </summary> + /// <param name="monitor">The monitor.</param> + /// <param name="value">The value.</param> + /// <returns></returns> + private List<List<double>> GetDataMatrix(TechMonitor monitor, object value) + { + DoubleArray[] arrayOfDoubles = Enumerable.ToArray(value as IEnumerable<DoubleArray>); + return arrayOfDoubles.Select(x => x.Data.ToList()).ToList(); + } + + #endregion + + #region Virtual Methods + + /// <summary> + /// Called when the disable rendering has been changed + /// </summary> + protected virtual void OnDisableRenderingChanged() + { + foreach (var controller in _singleControllers) + { + controller.Value.ChangeRenderMode(!DisableRendering); + } + + foreach (var controller in _multiControllers) + { + controller.Value.ChangeRenderMode(!DisableRendering); + } + } + + #endregion + + #region Add/Remove Element + + /// <summary> + /// Creates a new tech element by the specified bounds and the current selected element. + /// </summary> + /// <param name="bounds">The bounds.</param> + public void CreateElement(Rect bounds) + { + CreateElement(SelectedTechItem, bounds); + } + + /// <summary> + /// Creates a new tech element by the specified tech item instance and bounds. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="bounds">The bounds.</param> + private void CreateElement(TechItem item, Rect bounds) + { + if (item is MonitorItem) + { + CreateElement<MonitorElementEditor, MonitorItem, TechMonitor>(bounds, Adapter.TechMonitors.Where(x => !x.MultiChannel).FirstOrDefault()); + } + else if (item is MeterItem) + { + CreateElement<MeterElementEditor, MeterItem, TechMonitor>(bounds, Adapter.TechMonitors.Where(x => !x.MultiChannel).FirstOrDefault()); + } + else if (item is SingleGraphItem) + { + var editor = CreateElement<SingleGraphElementEditor, SingleGraphItem, TechMonitor>(bounds, Adapter.TechMonitors.Where(x => !x.MultiChannel).FirstOrDefault()); + InitSingleGraphitem(editor.GraphItem, editor); + } + else if (item is MultiGraphItem) + { + var editor = CreateElement<MultiGraphElementEditor, MultiGraphItem, TechMonitor>(bounds, Adapter.TechMonitors.Where(x => x.MultiChannel).FirstOrDefault()); + InitMultiGraphItem(editor.GraphItem, editor); + } + else if (item is MotorItem) + { + var editor = CreateElement<MotorElementEditor, MotorItem, TechMotor>(bounds, Adapter.TechMotors.FirstOrDefault()); + InitMotorItem(editor.MotorItem); + } + else if (item is DispenserItem) + { + var editor = CreateElement<DispenserElementEditor, DispenserItem, TechDispenser>(bounds, Adapter.TechDispensers.FirstOrDefault()); + InitDispenserItem(editor.DispenserItem); + } + else if (item is ThreadMotionItem) + { + var editor = CreateElement<ThreadMotionElementEditor, ThreadMotionItem, object>(bounds, null); + InitThreadMotionItem(editor.ThreadMotionItem); + } + else if (item is MotorGroupItem) + { + var editor = CreateElement<MotorGroupElementEditor, MotorGroupItem, object>(bounds, null); + InitMotorGroupItem(editor.MotorGroupItem); + } + else if (item is DigitalOutItem) + { + var editor = CreateElement<DigitalOutElementEditor, DigitalOutItem, TechIo>(bounds, Adapter.TechIos.Where(x => x.Type == IOType.DigitalOutput.ToInt32()).FirstOrDefault()); + InitDigitalOutItem(editor.DigitalOutItem); + } + else if (item is DigitalInItem) + { + CreateElement<DigitalInElementEditor, DigitalInItem, TechIo>(bounds, Adapter.TechIos.Where(x => x.Type == IOType.DigitalInput.ToInt32()).FirstOrDefault()); + } + } + + /// <summary> + /// Creates a new element by the specified editor type, tech item type, bounds and tech item constructor value. + /// </summary> + /// <typeparam name="Editor">The type of the editor.</typeparam> + /// <typeparam name="Tech">The type of the tech.</typeparam> + /// <typeparam name="Value">The type of the value.</typeparam> + /// <param name="bounds">The bounds.</param> + /// <param name="value">The value.</param> + /// <returns></returns> + private Editor CreateElement<Editor, Tech, Value>(Rect bounds, Value value) where Editor : IElementEditor where Tech : TechItem + { + TechItem item = Activator.CreateInstance(typeof(Tech), new object[] { value }) as TechItem; + IElementEditor editor = Activator.CreateInstance(typeof(Editor), new object[] { ((Tech)item), bounds }) as IElementEditor; + Elements.Add(editor); + return (Editor)editor; + } + + /// <summary> + /// Creates a new element by the specified editor type and tech item instance. + /// </summary> + /// <typeparam name="Editor">The type of the editor.</typeparam> + /// <param name="item">The item.</param> + /// <returns></returns> + private Editor CreateElement<Editor>(TechItem item) where Editor : IElementEditor + { + IElementEditor editor = Activator.CreateInstance(typeof(Editor), new object[] { item, item.GetBounds() }) as IElementEditor; + Elements.Add(editor); + return (Editor)editor; + } + + /// <summary> + /// Adds a new tech item. + /// </summary> + /// <param name="item">The item.</param> + private void AddTechItem(TechItem item) + { + if (item is MonitorItem) + { + (item as MonitorItem).TechMonitor = Adapter.TechMonitors.Where(x => !x.MultiChannel).FirstOrDefault(x => x.Guid == item.ItemGuid); + CreateElement<MonitorElementEditor>(item); + } + else if (item is MeterItem) + { + (item as MeterItem).TechMonitor = Adapter.TechMonitors.Where(x => !x.MultiChannel).FirstOrDefault(x => x.Guid == item.ItemGuid); + CreateElement<MeterElementEditor>(item); + } + else if (item is SingleGraphItem) + { + (item as SingleGraphItem).TechMonitor = Adapter.TechMonitors.Where(x => !x.MultiChannel).FirstOrDefault(x => x.Guid == item.ItemGuid); + var editor = CreateElement<SingleGraphElementEditor>(item); + InitSingleGraphitem(editor.GraphItem, editor); + } + else if (item is MultiGraphItem) + { + (item as MultiGraphItem).TechMonitor = Adapter.TechMonitors.Where(x => x.MultiChannel).FirstOrDefault(x => x.Guid == item.ItemGuid); + var editor = CreateElement<MultiGraphElementEditor>(item); + InitMultiGraphItem(editor.GraphItem, editor); + } + else if (item is MotorItem) + { + (item as MotorItem).TechMotor = Adapter.TechMotors.FirstOrDefault(x => x.Guid == item.ItemGuid); + var editor = CreateElement<MotorElementEditor>(item); + InitMotorItem(editor.MotorItem); + } + else if (item is DispenserItem) + { + (item as DispenserItem).TechDispenser = Adapter.TechDispensers.FirstOrDefault(x => x.Guid == item.ItemGuid); + var editor = CreateElement<DispenserElementEditor>(item); + InitDispenserItem(editor.DispenserItem); + } + else if (item is ThreadMotionItem) + { + var editor = CreateElement<ThreadMotionElementEditor>(item); + InitThreadMotionItem(editor.ThreadMotionItem); + } + else if (item is MotorGroupItem) + { + var editor = CreateElement<MotorGroupElementEditor>(item); + InitMotorGroupItem(editor.MotorGroupItem); + } + else if (item is DigitalOutItem) + { + (item as DigitalOutItem).TechIo = Adapter.TechIos.FirstOrDefault(x => x.Guid == item.ItemGuid); + var editor = CreateElement<DigitalOutElementEditor>(item); + InitDigitalOutItem(editor.DigitalOutItem); + } + else if (item is DigitalInItem) + { + (item as DigitalInItem).TechIo = Adapter.TechIos.FirstOrDefault(x => x.Guid == item.ItemGuid); + CreateElement<DigitalInElementEditor>(item); + } + } + + /// <summary> + /// Called when elements have been removed + /// </summary> + /// <param name="elements">The elements.</param> + public void OnElementsRemoved(List<IElementEditor> elements) + { + //foreach (var element in elements) + //{ + // if (element.HostedElement is SingleGraphItem) + // { + // _singleControllers.Remove(element.HostedElement as SingleGraphItem); + // (element.HostedElement as SingleGraphItem).Editor.InnerGraph.InnerGraph.Dispose(); + // } + // else if (element.HostedElement is MultiGraphItem) + // { + // _multiControllers.Remove(element.HostedElement as MultiGraphItem); + // (element.HostedElement as MultiGraphItem).Editor.InnerGraph.InnerGraph.Dispose(); + // } + //} + } + + /// <summary> + /// Called when elements have been pasted + /// </summary> + /// <param name="elements">The elements.</param> + public void OnElementsPasted(List<IElementEditor> elements) + { + foreach (var element in elements) + { + if (element is SingleGraphElementEditor) + { + var graphItem = element.HostedElement as SingleGraphItem; + var editor = element as SingleGraphElementEditor; + graphItem.Editor = editor; + editor.InnerGraph.InnerGraph.MaxPoints = Common.Helpers.GraphsHelper.GetMaxPoints(graphItem.TechMonitor.PointsPerFrame); + + GraphController controller = new GraphController(); + editor.InnerGraph.Controller = controller; + + _singleControllers.Add(graphItem, controller); + } + else if (element is MultiGraphElementEditor) + { + var graphItem = element.HostedElement as MultiGraphItem; + var editor = element as MultiGraphElementEditor; + editor.InnerGraph.InnerGraph.MaxPoints = Common.Helpers.GraphsHelper.GetMaxPoints(graphItem.TechMonitor.PointsPerFrame); + graphItem.Editor = editor; + + + GraphMultiController controller = new GraphMultiController(); + + for (int i = 0; i < graphItem.TechMonitor.ChannelCount; i++) + { + controller.AddSeries(new RealTimeGraphEx.DataSeries.DataYSeries() + { + UseFillAndStroke = true, + Name = graphItem.TechMonitor.Name.First() + (i + 1).ToString(), + Stroke = new SolidColorBrush(ColorHelper.GetRandomColor()), + }); + } + + editor.InnerGraph.Controller = controller; + + _multiControllers.Add(graphItem, controller); + } + else if (element is MotorElementEditor) + { + var motorItem = element.HostedElement as MotorItem; + InitMotorItem(motorItem); + } + else if (element is DispenserElementEditor) + { + var dispenser = element.HostedElement as DispenserItem; + InitDispenserItem(dispenser); + } + else if (element is DigitalOutItem) + { + var ioItem = element.HostedElement as DigitalOutItem; + InitDigitalOutItem(ioItem); + } + else if (element is ThreadMotionItem) + { + var threadMotionItem = element.HostedElement as ThreadMotionItem; + InitThreadMotionItem(threadMotionItem); + } + else if (element is MotorGroupItem) + { + var motorGroupItem = element.HostedElement as MotorGroupItem; + InitMotorGroupItem(motorGroupItem); + } + } + } + + #endregion + + #region Init Tech Items + + /// <summary> + /// Initializes the motor item. + /// </summary> + /// <param name="item">The item.</param> + private void InitMotorItem(MotorItem item) + { + item.ActionExecuted += async (x, action) => + { + if (action == MotorActionType.ForwardPressed) + { + await MachineOperator.StartMotorJogging(new MotorJoggingRequest() + { + Code = item.TechMotor.Code, + Direction = MotorDirection.Forward, + }); + } + else if (action == MotorActionType.ForwardReleased) + { + await MachineOperator.StopMotorJogging(new MotorAbortJoggingRequest() + { + Code = item.TechMotor.Code, + }); + } + else if (action == MotorActionType.BackwardPressed) + { + await MachineOperator.StartMotorJogging(new MotorJoggingRequest() + { + Code = item.TechMotor.Code, + Direction = MotorDirection.Backward, + }); + } + else if (action == MotorActionType.BackwardReleased) + { + await MachineOperator.StopMotorJogging(new MotorAbortJoggingRequest() + { + Code = item.TechMotor.Code, + }); + } + else if (action == MotorActionType.HomingStarted) + { + item.HomingProgress = 0; + item.IsHoming = true; + item.IsHomingCompleted = false; + + MachineOperator.StartMotorHoming(new MotorHomingRequest() + { + Code = item.TechMotor.Code + }) + .Subscribe((response) => + { + + item.HomingMaximumProgress = response.Message.MaxProgress; + item.HomingProgress = response.Message.Progress; + + }, () => + { + + item.IsHoming = false; + item.IsHomingCompleted = true; + + }); + } + else if (action == MotorActionType.HomingStopped) + { + await MachineOperator.StopMotorHoming(new MotorAbortHomingRequest() + { + Code = item.TechMotor.Code, + }); + + item.IsHoming = false; + } + }; + } + + /// <summary> + /// Initializes the dispenser item. + /// </summary> + /// <param name="item">The item.</param> + private void InitDispenserItem(DispenserItem item) + { + item.ActionExecuted += async (x, action) => + { + if (action == MotorActionType.ForwardPressed) + { + await MachineOperator.StartDispenserJogging(new DispenserJoggingRequest() + { + Code = item.TechDispenser.Code, + Direction = MotorDirection.Forward, + }); + } + else if (action == MotorActionType.ForwardReleased) + { + await MachineOperator.StopDispenserJogging(new DispenserAbortJoggingRequest() + { + Code = item.TechDispenser.Code, + }); + } + else if (action == MotorActionType.BackwardPressed) + { + await MachineOperator.StartDispenserJogging(new DispenserJoggingRequest() + { + Code = item.TechDispenser.Code, + Direction = MotorDirection.Backward, + }); + } + else if (action == MotorActionType.BackwardReleased) + { + await MachineOperator.StopDispenserJogging(new DispenserAbortJoggingRequest() + { + Code = item.TechDispenser.Code, + }); + } + else if (action == MotorActionType.HomingStarted) + { + item.HomingProgress = 0; + item.IsHoming = true; + item.IsHomingCompleted = false; + + MachineOperator.StartDispenserHoming(new DispenserHomingRequest() + { + Code = item.TechDispenser.Code + }) + .Subscribe((response) => + { + + item.HomingMaximumProgress = response.Message.MaxProgress; + item.HomingProgress = response.Message.Progress; + + }, () => + { + + item.IsHoming = false; + item.IsHomingCompleted = true; + + }); + } + else if (action == MotorActionType.HomingStopped) + { + await MachineOperator.StopDispenserHoming(new DispenserAbortHomingRequest() + { + Code = item.TechDispenser.Code, + }); + + item.IsHoming = false; + } + }; + } + + /// <summary> + /// Initializes the single graph item. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="editor">The editor.</param> + private void InitSingleGraphitem(SingleGraphItem item, SingleGraphElementEditor editor) + { + editor.InnerGraph.InnerGraph.MaxPoints = Common.Helpers.GraphsHelper.GetMaxPoints(item.TechMonitor.PointsPerFrame); + item.Editor = editor; + + GraphController controller = new GraphController(); + editor.InnerGraph.Controller = controller; + + _singleControllers.Add(item, controller); + } + + /// <summary> + /// Initializes the multi graph item. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="editor">The editor.</param> + private void InitMultiGraphItem(MultiGraphItem item, MultiGraphElementEditor editor) + { + editor.InnerGraph.InnerGraph.MaxPoints = Common.Helpers.GraphsHelper.GetMaxPoints(item.TechMonitor.PointsPerFrame); + item.Editor = editor; + + GraphMultiController controller = new GraphMultiController(); + + for (int i = 0; i < item.TechMonitor.ChannelCount; i++) + { + controller.AddSeries(new RealTimeGraphEx.DataSeries.DataYSeries() + { + UseFillAndStroke = true, + Name = item.TechMonitor.Name.First() + (i + 1).ToString(), + Stroke = new SolidColorBrush(ColorHelper.GetRandomColor()), + }); + } + + editor.InnerGraph.Controller = controller; + + _multiControllers.Add(item, controller); + } + + /// <summary> + /// Initializes the thread motion item. + /// </summary> + /// <param name="item">The item.</param> + private void InitThreadMotionItem(ThreadMotionItem item) + { + item.ActionExecuted += async (x, action) => + { + if (action == MotorActionType.ForwardPressed) + { + await MachineOperator.StartThreadJogging(new ThreadJoggingRequest() + { + Direction = MotorDirection.Forward, + }); + } + else if (action == MotorActionType.BackwardPressed) + { + await MachineOperator.StartThreadJogging(new ThreadJoggingRequest() + { + Direction = MotorDirection.Backward, + }); + } + else if (action == MotorActionType.ForwardReleased || action == MotorActionType.BackwardReleased) + { + await MachineOperator.StopThreadJogging(new ThreadAbortJoggingRequest()); + } + }; + } + + /// <summary> + /// Initializes the motor group item. + /// </summary> + /// <param name="item">The item.</param> + private void InitMotorGroupItem(MotorGroupItem item) + { + item.ActionExecuted += async (x, action) => + { + if (action == MotorActionType.ForwardPressed) + { + await Task.WhenAll(item.TechMotors.Select(motor => MachineOperator.StartMotorJogging(new MotorJoggingRequest() + { + Code = motor.Code, + Direction = MotorDirection.Forward, + }))); + } + else if (action == MotorActionType.ForwardReleased) + { + await Task.WhenAll(item.TechMotors.Select(motor => MachineOperator.StopMotorJogging(new MotorAbortJoggingRequest() + { + Code = motor.Code, + }))); + } + else if (action == MotorActionType.BackwardPressed) + { + await Task.WhenAll(item.TechMotors.Select(motor => MachineOperator.StartMotorJogging(new MotorJoggingRequest() + { + Code = motor.Code, + Direction = MotorDirection.Backward, + }))); + } + else if (action == MotorActionType.BackwardReleased) + { + await Task.WhenAll(item.TechMotors.Select(motor => MachineOperator.StopMotorJogging(new MotorAbortJoggingRequest() + { + Code = motor.Code, + }))); + } + //else if (action == MotorActionType.HomingStarted) + //{ + // item.HomingProgress = 0; + // item.IsHoming = true; + // item.IsHomingCompleted = false; + + // MachineOperator.StartMotorHoming(new MotorHomingRequest() + // { + // Code = item.TechMotor.Code + // }) + // .Subscribe((response) => + // { + + // item.HomingMaximumProgress = response.Message.MaxProgress; + // item.HomingProgress = response.Message.Progress; + + // }, () => + // { + + // item.IsHoming = false; + // item.IsHomingCompleted = true; + + // }); + //} + //else if (action == MotorActionType.HomingStopped) + //{ + // await MachineOperator.StopMotorHoming(new MotorAbortHomingRequest() + // { + // Code = item.TechMotor.Code, + // }); + + // item.IsHoming = false; + //} + }; + } + + /// <summary> + /// Initializes the digital out item. + /// </summary> + /// <param name="item">The item.</param> + private void InitDigitalOutItem(DigitalOutItem item) + { + item.ValueChanged += async (x, value) => + { + try + { + await MachineOperator.SetDigitalOut(new SetDigitalOutRequest() { Port = item.TechIo.Port, Value = value }); + } + catch (Exception ex) + { + //TODO: Show Exception. + } + }; + } + + #endregion + + #region Public Methods + + /// <summary> + /// Opens a file open dialog to select a project file. + /// </summary> + public void OpenProject() + { + OpenFileDialog dlg = new OpenFileDialog(); + dlg.Title = "Select Technician Project File"; + dlg.Filter = "Technician Project File|*.tpf"; + + if (dlg.ShowDialog().Value) + { + OpenProjectFile(dlg.FileName); + } + } + + /// <summary> + /// Opens the specified project file path. + /// </summary> + /// <param name="fileName">File path.</param> + public void OpenProjectFile(String fileName) + { + LoadProject(MachineTechViewProject.Load(fileName)); + _lastTechProjectFile = fileName; + } + + /// <summary> + /// Loads the specified project. + /// </summary> + /// <param name="project">The project.</param> + public void LoadProject(MachineTechViewProject project) + { + using (_notification.PushTaskItem("Loading technician project file...")) + { + Elements.Clear(); + _singleControllers.Clear(); + _multiControllers.Clear(); + + foreach (var item in project.Items) + { + if (item is MotorGroupItem) + { + (item as MotorGroupItem).TechMotors = ObservablesEntitiesAdapter.Instance.TechMotors.Where(x => (item as MotorGroupItem).ItemsGuids.Contains(x.Guid)).ToObservableCollection(); + } + + AddTechItem(item); + } + } + } + + /// <summary> + /// Opens the file save dialog for selecting a project file target. + /// </summary> + private void SaveAsProject() + { + SaveFileDialog dlg = new SaveFileDialog(); + dlg.Title = "Select Technician Project Location"; + dlg.Filter = "Technician Project File|*.tpf"; + + if (dlg.ShowDialog().Value) + { + SaveProjectFile(dlg.FileName); + } + } + + /// <summary> + /// Saves the current project to the specified file path. + /// </summary> + /// <param name="fileName">Name of the file.</param> + private void SaveProjectFile(String fileName) + { + using (_notification.PushTaskItem("Saving technician project file...")) + { + MachineTechViewProject project = GenerateProjectFile(); + project.Save(fileName); + _lastTechProjectFile = fileName; + } + } + + /// <summary> + /// Saves the current opened project file. If not project file is opened will call <see cref="SaveAsProject"/>. + /// </summary> + private void SaveProject() + { + if (File.Exists(_lastTechProjectFile)) + { + SaveProjectFile(_lastTechProjectFile); + } + else + { + SaveAsProject(); + } + } + + /// <summary> + /// Generates a project file from the current element setup. + /// </summary> + /// <returns></returns> + private MachineTechViewProject GenerateProjectFile() + { + MachineTechViewProject project = new MachineTechViewProject(); + + foreach (var element in Elements) + { + if (element.HostedElement is MotorGroupItem) + { + var group = element.HostedElement as MotorGroupItem; + group.ItemsGuids = group.TechMotors.Select(x => x.Guid).ToList(); + } + + (element.HostedElement as TechItem).SetBounds(element.GetBounds()); + project.Items.Add(element.HostedElement as TechItem); + } + + return project; + } + + #endregion + + #region IShutdownListener + + /// <summary> + /// Called when the application is about to terminate. + /// </summary> + public void OnShuttingDown() + { + InvokeUINow(() => + { + SettingsManager.Default.MachineStudio.TechnicianModule.LasTechProjectFile = _lastTechProjectFile; + }); + } + + #endregion + } +} |
