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.BL.Entities;
using Tango.Integration.Operation;
using Tango.MachineStudio.Common.Diagnostics;
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;
using Tango.Integration.Services;
using Tango.BL.Enumerations;
using Tango.BL;
using Tango.MachineStudio.Common.EventLogging;
using Tango.MachineStudio.Common;
using Tango.Core.Commands;
using Tango.MachineStudio.Technician.Helpers;
namespace Tango.MachineStudio.Technician.ViewModels
{
///
/// Represents the MachineTechView View Model.
///
///
///
public class MachineTechViewVM : StudioViewModel
{
private List _diagnoticsMonitorsDataProperties;
private Dictionary _singleControllers;
private Dictionary _multiControllers;
private static object _elementsLock = new object();
private String _lastTechProjectFile;
private INotificationProvider _notification;
private IEventLogger _eventLogger;
private DateTime _lastDiagnosticsResponseUpdate;
private const int MIN_DIAGNOSTICS_UPDATE_MILI = 500;
private TechnicianModuleSettings _settings;
#region Properties
private ObservableCollection _elements;
///
/// Gets or sets the visual elements.
///
public ObservableCollection Elements
{
get { return _elements; }
set { _elements = value; RaisePropertyChangedAuto(); }
}
private ObservableCollection _availableTechItems;
///
/// Gets or sets the available tech items.
///
public ObservableCollection AvailableTechItems
{
get { return _availableTechItems; }
set { _availableTechItems = value; RaisePropertyChangedAuto(); }
}
private TechItem _selectedTechItem;
///
/// Gets or sets the selected available tech item.
///
public TechItem SelectedTechItem
{
get { return _selectedTechItem; }
set { _selectedTechItem = value; RaisePropertyChangedAuto(); }
}
///
/// Gets or sets the db adapter.
///
public ObservablesEntitiesAdapter Adapter { get; set; }
///
/// Gets or sets the application manager.
///
public IStudioApplicationManager ApplicationManager { get; set; }
private IMachineOperator _machineOperator;
///
/// Gets or sets the machine operator.
///
public IMachineOperator MachineOperator
{
get { return _machineOperator; }
set { _machineOperator = value; RaisePropertyChangedAuto(); }
}
private bool _disableRendering;
///
/// Gets or sets a value indicating whether [disable rendering].
///
public bool DisableRendering
{
get { return _disableRendering; }
set { _disableRendering = value; RaisePropertyChangedAuto(); OnDisableRenderingChanged(); }
}
private bool _hideMenu;
///
/// Gets or sets a value indicating whether [hide menu].
///
public bool HideMenu
{
get { return _hideMenu; }
set { _hideMenu = value; RaisePropertyChangedAuto(); }
}
private StartDiagnosticsResponse _currentDiagnosticsResponse;
///
/// Gets or sets the current diagnostics response.
///
public StartDiagnosticsResponse CurrentDiagnosticsResponse
{
get { return _currentDiagnosticsResponse; }
set { _currentDiagnosticsResponse = value; RaisePropertyChanged(nameof(CurrentDiagnosticsResponse)); }
}
private int _currentDiagnosticsResponseSize;
///
/// Gets or sets the size of the current diagnostics response.
///
///
/// The size of the current diagnostics response.
///
public int CurrentDiagnosticsResponseSize
{
get { return _currentDiagnosticsResponseSize; }
set { _currentDiagnosticsResponseSize = value; RaisePropertyChanged(nameof(CurrentDiagnosticsResponseSize)); }
}
#endregion
#region Commands
///
/// Gets or sets the save as project command.
///
public RelayCommand SaveAsProjectCommand { get; set; }
///
/// Gets or sets the save project command.
///
public RelayCommand SaveProjectCommand { get; set; }
///
/// Gets or sets the open project command.
///
public RelayCommand OpenProjectCommand { get; set; }
///
/// Gets or sets the synchronize hardware configuration command.
///
public RelayCommand SyncHardwareConfigurationCommand { get; set; }
///
/// Gets or sets the upload hardware configuration command.
///
public RelayCommand UploadHardwareConfigurationCommand { get; set; }
///
/// Gets or sets the reset hardware configuration command.
///
public RelayCommand ResetHardwareConfigurationCommand { get; set; }
#endregion
#region Constructors
///
/// Initializes a new instance of the class.
///
/// The application manager.
/// The notification provider.
public MachineTechViewVM(IStudioApplicationManager applicationManager, INotificationProvider notificationProvider, IDiagnosticsFrameProvider _diagnosticsFrameProvider, IEventLogger eventLogger)
{
_settings = SettingsManager.Default.GetOrCreate();
_notification = notificationProvider;
_eventLogger = eventLogger;
_singleControllers = new Dictionary();
_multiControllers = new Dictionary();
AvailableTechItems = TechItem.GetAvailableTechItems().ToObservableCollection();
SelectedTechItem = AvailableTechItems.FirstOrDefault();
_diagnoticsMonitorsDataProperties = typeof(DiagnosticsMonitors).GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList();
ApplicationManager = applicationManager;
ApplicationManager.ConnectedMachineChanged += ApplicationManager_ConnectedMachineChanged;
Adapter = ObservablesEntitiesAdapter.Instance;
Elements = new ObservableCollection();
OpenProjectCommand = new RelayCommand(OpenProject);
SaveAsProjectCommand = new RelayCommand(SaveAsProject);
SaveProjectCommand = new RelayCommand(SaveProject);
_lastTechProjectFile = _settings.LastTechProjectFile;
if (File.Exists(_lastTechProjectFile))
{
OpenProjectFile(_lastTechProjectFile);
}
_diagnosticsFrameProvider.FrameReceived += DiagnosticsFrameProvider_FrameReceived;
UploadHardwareConfigurationCommand = new RelayCommand(UploadHardwareConfiguration);
SyncHardwareConfigurationCommand = new RelayCommand(SyncHardwareConfiguration);
ResetHardwareConfigurationCommand = new RelayCommand(() => ResetHardwareConfiguration());
}
#endregion
#region Event Handlers
///
/// Applications the manager connected machine changed.
///
/// The sender.
/// The machine.
private void ApplicationManager_ConnectedMachineChanged(object sender, IExternalBridgeClient machine)
{
MachineOperator = machine;
if (MachineOperator != null)
{
ResetHardwareConfiguration(false);
}
}
///
/// Handles the diagnostics frame provider data.
///
/// The sender.
/// The response.
private void DiagnosticsFrameProvider_FrameReceived(object sender, StartDiagnosticsResponse response)
{
PopulateDiagnosticsData(response);
}
#endregion
#region Populate Diagnostics Data
///
/// Populates the diagnostics data to the proper elements.
///
/// The data.
private void PopulateDiagnosticsData(StartDiagnosticsResponse 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 = _diagnoticsMonitorsDataProperties.SingleOrDefault(x => x.Name == monitorItem.TechMonitor.Name);
if (prop != null)
{
monitorItem.Value = GetDataLastValue(monitorItem.TechMonitor, prop.GetValue(data.Monitors));
}
}
}
else if (item.GetType() == typeof(MeterItem))
{
MeterItem meterItem = item as MeterItem;
if (DateTime.Now > meterItem.LastUpdateTime.AddMilliseconds(meterItem.UpdateInterval))
{
var prop = _diagnoticsMonitorsDataProperties.SingleOrDefault(x => x.Name == meterItem.TechMonitor.Name);
if (prop != null)
{
meterItem.Value = GetDataLastValue(meterItem.TechMonitor, prop.GetValue(data.Monitors));
}
}
}
else if (item.GetType() == typeof(SingleGraphItem))
{
SingleGraphItem graphItem = item as SingleGraphItem;
var prop = _diagnoticsMonitorsDataProperties.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.Monitors)));
}
}
}
else if (item.GetType() == typeof(MultiGraphItem))
{
MultiGraphItem graphItem = item as MultiGraphItem;
var prop = _diagnoticsMonitorsDataProperties.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.Monitors)));
}
}
}
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;
}
}
else if (item.GetType() == typeof(ControllerItem))
{
ControllerItem controllerItem = item as ControllerItem;
if (DateTime.Now > controllerItem.LastUpdateTime.AddMilliseconds(controllerItem.UpdateInterval))
{
var componentState = data.ComponentsStates.SingleOrDefault(x => (int)x.Component == controllerItem.TechController.Code);
if (componentState != null)
{
controllerItem.EffectiveValue = componentState.Value;
}
}
}
}
}
}
#endregion
#region Private Methods
///
/// Gets the last data point from a protobuf repeated field.
///
/// The monitor.
/// The value.
///
private double GetDataLastValue(TechMonitor monitor, object value)
{
if (!monitor.MultiChannel)
{
RepeatedField arr = value as RepeatedField;
return arr.LastOrDefault();
}
else
{
RepeatedField arr = value as RepeatedField;
return arr.Last().Data.Last();
}
}
///
/// Gets the data array from a protobuf repeated field.
///
/// The monitor.
/// The value.
///
private List GetDataArray(TechMonitor monitor, object value)
{
return (value as RepeatedField).ToList();
}
///
/// Gets the data matrix from a protobuf repeated field of .
///
/// The monitor.
/// The value.
///
private List> GetDataMatrix(TechMonitor monitor, object value)
{
DoubleArray[] arrayOfDoubles = Enumerable.ToArray(value as IEnumerable);
return arrayOfDoubles.Select(x => x.Data.ToList()).ToList();
}
#endregion
#region Virtual Methods
///
/// Called when the disable rendering has been changed
///
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
///
/// Creates a new tech element by the specified bounds and the current selected element.
///
/// The bounds.
public void CreateElement(Rect bounds)
{
CreateElement(SelectedTechItem, bounds);
}
///
/// Creates a new tech element by the specified tech item instance and bounds.
///
/// The item.
/// The bounds.
private void CreateElement(TechItem item, Rect bounds)
{
if (item is MonitorItem)
{
CreateElement(bounds, Adapter.TechMonitors.Where(x => !x.MultiChannel).FirstOrDefault());
}
else if (item is MeterItem)
{
CreateElement(bounds, Adapter.TechMonitors.Where(x => !x.MultiChannel).FirstOrDefault());
}
else if (item is SingleGraphItem)
{
var editor = CreateElement(bounds, Adapter.TechMonitors.Where(x => !x.MultiChannel).FirstOrDefault());
InitSingleGraphitem(editor.GraphItem, editor);
}
else if (item is MultiGraphItem)
{
var editor = CreateElement(bounds, Adapter.TechMonitors.Where(x => x.MultiChannel).FirstOrDefault());
InitMultiGraphItem(editor.GraphItem, editor);
}
else if (item is MotorItem)
{
var editor = CreateElement(bounds, Adapter.HardwareMotorTypes.FirstOrDefault());
InitMotorItem(editor.MotorItem);
}
else if (item is DispenserItem)
{
var editor = CreateElement(bounds, Adapter.TechDispensers.FirstOrDefault());
InitDispenserItem(editor.DispenserItem);
}
else if (item is ThreadMotionItem)
{
var editor = CreateElement(bounds, null);
InitThreadMotionItem(editor.ThreadMotionItem);
}
else if (item is MotorGroupItem)
{
var editor = CreateElement(bounds, null);
InitMotorGroupItem(editor.MotorGroupItem);
}
else if (item is DigitalOutItem)
{
var editor = CreateElement(bounds, Adapter.TechIos.Where(x => x.Type == IOType.DigitalOutput.ToInt32()).FirstOrDefault());
InitDigitalOutItem(editor.DigitalOutItem);
}
else if (item is DigitalInItem)
{
CreateElement(bounds, Adapter.TechIos.Where(x => x.Type == IOType.DigitalInput.ToInt32()).FirstOrDefault());
}
else if (item is ControllerItem)
{
var editor = CreateElement(bounds, Adapter.TechControllers.FirstOrDefault());
InitControllerItem(editor.ControllerItem);
}
else if (item is PidItem)
{
CreateElement(bounds, Adapter.HardwarePidControlTypes.FirstOrDefault());
}
else if (item is WinderItem)
{
CreateElement(bounds, Adapter.HardwareWinderTypes.FirstOrDefault());
}
else if (item is DancerItem)
{
CreateElement(bounds, Adapter.HardwareDancerTypes.FirstOrDefault());
}
else if (item is SpeedSensorItem)
{
CreateElement(bounds, Adapter.HardwareSpeedSensorTypes.FirstOrDefault());
}
else if (item is ProcessParametersItem)
{
var editor = CreateElement(bounds, null);
InitProcessParameterItem(editor.ProcessParametersItem);
}
else if (item is JobRunnerItem)
{
var editor = CreateElement(bounds, null);
InitJobRunnerItem(editor.JobRunnerItem);
}
}
///
/// Creates a new element by the specified editor type, tech item type, bounds and tech item constructor value.
///
/// The type of the editor.
/// The type of the tech.
/// The type of the value.
/// The bounds.
/// The value.
///
private Editor CreateElement(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;
}
///
/// Creates a new element by the specified editor type and tech item instance.
///
/// The type of the editor.
/// The item.
///
private Editor CreateElement(TechItem item) where Editor : IElementEditor
{
IElementEditor editor = Activator.CreateInstance(typeof(Editor), new object[] { item, item.GetBounds() }) as IElementEditor;
Elements.Add(editor);
return (Editor)editor;
}
///
/// Adds a new tech item.
///
/// The item.
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(item);
}
else if (item is MeterItem)
{
(item as MeterItem).TechMonitor = Adapter.TechMonitors.Where(x => !x.MultiChannel).FirstOrDefault(x => x.Guid == item.ItemGuid);
CreateElement(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(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(item);
InitMultiGraphItem(editor.GraphItem, editor);
}
else if (item is MotorItem)
{
(item as MotorItem).HardwareMotorType = Adapter.HardwareMotorTypes.FirstOrDefault(x => x.Guid == item.ItemGuid);
var editor = CreateElement(item);
InitMotorItem(editor.MotorItem);
}
else if (item is DispenserItem)
{
(item as DispenserItem).TechDispenser = Adapter.TechDispensers.FirstOrDefault(x => x.Guid == item.ItemGuid);
var editor = CreateElement(item);
InitDispenserItem(editor.DispenserItem);
}
else if (item is ThreadMotionItem)
{
var editor = CreateElement(item);
InitThreadMotionItem(editor.ThreadMotionItem);
}
else if (item is MotorGroupItem)
{
var editor = CreateElement(item);
InitMotorGroupItem(editor.MotorGroupItem);
}
else if (item is DigitalOutItem)
{
(item as DigitalOutItem).TechIo = Adapter.TechIos.FirstOrDefault(x => x.Guid == item.ItemGuid);
var editor = CreateElement(item);
InitDigitalOutItem(editor.DigitalOutItem);
}
else if (item is DigitalInItem)
{
(item as DigitalInItem).TechIo = Adapter.TechIos.FirstOrDefault(x => x.Guid == item.ItemGuid);
CreateElement(item);
}
else if (item is ControllerItem)
{
(item as ControllerItem).TechController = Adapter.TechControllers.FirstOrDefault(x => x.Guid == item.ItemGuid);
var editor = CreateElement(item);
InitControllerItem(editor.ControllerItem);
}
else if (item is PidItem)
{
(item as PidItem).HardwarePidType = Adapter.HardwarePidControlTypes.FirstOrDefault(x => x.Guid == item.ItemGuid);
CreateElement(item);
}
else if (item is WinderItem)
{
(item as WinderItem).HardwareWinderType = Adapter.HardwareWinderTypes.FirstOrDefault(x => x.Guid == item.ItemGuid);
CreateElement(item);
}
else if (item is DancerItem)
{
(item as DancerItem).HardwareDancerType = Adapter.HardwareDancerTypes.FirstOrDefault(x => x.Guid == item.ItemGuid);
CreateElement(item);
}
else if (item is SpeedSensorItem)
{
(item as SpeedSensorItem).HardwareSpeedSensorType = Adapter.HardwareSpeedSensorTypes.FirstOrDefault(x => x.Guid == item.ItemGuid);
CreateElement(item);
}
else if (item is ProcessParametersItem)
{
var editor = CreateElement(item);
InitProcessParameterItem(editor.ProcessParametersItem);
}
else if (item is JobRunnerItem)
{
var editor = CreateElement(item);
InitJobRunnerItem(editor.JobRunnerItem);
}
}
///
/// Called when elements have been removed
///
/// The elements.
public void OnElementsRemoved(List 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();
// }
//}
}
///
/// Called when elements have been pasted
///
/// The elements.
public void OnElementsPasted(List 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 = 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 = 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);
}
else if (element is ControllerItem)
{
var controllerItem = element.HostedElement as ControllerItem;
InitControllerItem(controllerItem);
}
}
}
#endregion
#region Init Tech Items
///
/// Initializes the motor item.
///
/// The item.
private void InitMotorItem(MotorItem item)
{
item.ActionExecuted += async (x, action) =>
{
try
{
CheckMachineOperator();
if (action == MotorActionType.ForwardPressed)
{
await MachineOperator.StartMotorJogging(new MotorJoggingRequest()
{
Code = item.HardwareMotorType.Code,
Direction = MotorDirection.Forward,
});
}
else if (action == MotorActionType.ForwardReleased)
{
await MachineOperator.StopMotorJogging(new MotorAbortJoggingRequest()
{
Code = item.HardwareMotorType.Code,
});
}
else if (action == MotorActionType.BackwardPressed)
{
await MachineOperator.StartMotorJogging(new MotorJoggingRequest()
{
Code = item.HardwareMotorType.Code,
Direction = MotorDirection.Backward,
});
}
else if (action == MotorActionType.BackwardReleased)
{
await MachineOperator.StopMotorJogging(new MotorAbortJoggingRequest()
{
Code = item.HardwareMotorType.Code,
});
}
else if (action == MotorActionType.HomingStarted)
{
item.HomingProgress = 0;
item.IsHoming = true;
item.IsHomingCompleted = false;
MachineOperator.StartMotorHoming(new MotorHomingRequest()
{
Code = item.HardwareMotorType.Code
})
.Subscribe((response) =>
{
item.HomingMaximumProgress = response.MaxProgress;
item.HomingProgress = response.Progress;
}, () =>
{
item.IsHoming = false;
item.IsHomingCompleted = true;
});
}
else if (action == MotorActionType.HomingStopped)
{
await MachineOperator.StopMotorHoming(new MotorAbortHomingRequest()
{
Code = item.HardwareMotorType.Code,
});
item.IsHoming = false;
}
}
catch (Exception ex)
{
LogManager.Log(ex, String.Format("Error executing technician command '{0}' on item '{1}'.", action, item.TechName));
_eventLogger.Log(ex, String.Format("Error executing technician command '{0}' on item '{1}'.", action, item.TechName));
}
};
}
///
/// Initializes the dispenser item.
///
/// The item.
private void InitDispenserItem(DispenserItem item)
{
item.ActionExecuted += async (x, action) =>
{
try
{
CheckMachineOperator();
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.MaxProgress;
item.HomingProgress = response.Progress;
}, () =>
{
item.IsHoming = false;
item.IsHomingCompleted = true;
});
}
else if (action == MotorActionType.HomingStopped)
{
await MachineOperator.StopDispenserHoming(new DispenserAbortHomingRequest()
{
Code = item.TechDispenser.Code,
});
item.IsHoming = false;
}
}
catch (Exception ex)
{
LogManager.Log(ex, String.Format("Error executing technician command '{0}' on item '{1}'.", action, item.TechName));
_eventLogger.Log(ex, String.Format("Error executing technician command '{0}' on item '{1}'.", action, item.TechName));
}
};
}
///
/// Initializes the single graph item.
///
/// The item.
/// The editor.
private void InitSingleGraphitem(SingleGraphItem item, SingleGraphElementEditor editor)
{
editor.InnerGraph.InnerGraph.MaxPoints = GraphsHelper.GetMaxPoints(item.TechMonitor.PointsPerFrame);
item.Editor = editor;
GraphController controller = new GraphController();
editor.InnerGraph.Controller = controller;
_singleControllers.Add(item, controller);
}
///
/// Initializes the multi graph item.
///
/// The item.
/// The editor.
private void InitMultiGraphItem(MultiGraphItem item, MultiGraphElementEditor editor)
{
editor.InnerGraph.InnerGraph.MaxPoints = 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);
}
///
/// Initializes the thread motion item.
///
/// The item.
private void InitThreadMotionItem(ThreadMotionItem item)
{
item.ActionExecuted += async (x, action) =>
{
try
{
CheckMachineOperator();
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());
}
}
catch (Exception ex)
{
LogManager.Log(ex, String.Format(String.Format("Error executing technician command '{0}' on item '{1}'.", action, item.TechName)));
_eventLogger.Log(ex, String.Format("Error executing technician command '{0}' on item '{1}'.", action, item.TechName));
}
};
}
///
/// Initializes the motor group item.
///
/// The item.
private void InitMotorGroupItem(MotorGroupItem item)
{
item.ActionExecuted += async (x, action) =>
{
try
{
CheckMachineOperator();
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;
//}
}
catch (Exception ex)
{
LogManager.Log(ex, String.Format("Error executing technician command '{0}' on item '{1}'.", action, item.TechName));
_eventLogger.Log(ex, String.Format("Error executing technician command '{0}' on item '{1}'.", action, item.TechName));
}
};
}
///
/// Initializes the digital out item.
///
/// The item.
private void InitDigitalOutItem(DigitalOutItem item)
{
item.ValueChanged += async (x, value) =>
{
try
{
CheckMachineOperator();
await MachineOperator.SetDigitalOut(new SetDigitalOutRequest() { Port = item.TechIo.Port, Value = value });
}
catch (Exception ex)
{
LogManager.Log(ex, String.Format("Error executing technician set digital out command on '{0}'.", item.TechName));
_eventLogger.Log(ex, String.Format("Error executing technician set digital out command on '{0}'.", item.TechName));
}
};
}
///
/// Initializes the controller item.
///
/// The controller item.
private void InitControllerItem(ControllerItem item)
{
item.ValueChanged += async (x, value) =>
{
try
{
CheckMachineOperator();
await MachineOperator.SetComponentValue(new SetComponentValueRequest()
{
Component = (ValueComponent)item.TechController.Code,
Value = value
});
}
catch (Exception ex)
{
LogManager.Log(ex, String.Format("Error executing technician set value component command on '{0}'.", item.TechName));
_eventLogger.Log(ex, String.Format("Error executing technician set value component command on '{0}'.", item.TechName));
}
};
}
///
/// Initializes the process parameter item.
///
/// The item.
private void InitProcessParameterItem(ProcessParametersItem item)
{
item.PushParametersPressed += async (x, parameters) =>
{
try
{
CheckMachineOperator();
using (_notification.PushTaskItem("Uploading process parameters..."))
{
try
{
await MachineOperator.UploadProcessParameters(parameters);
}
catch (Exception ex)
{
String msg = "Error uploading process parameters:" + Environment.NewLine + parameters.ToJsonString();
_eventLogger.Log(ex,msg);
LogManager.Log(ex, msg);
_notification.ShowError("Could not upload process parameters." + Environment.NewLine + ex.Message);
}
}
}
catch (Exception ex)
{
_notification.ShowError(ex.Message);
}
};
}
///
/// Initializes the job runner item.
///
/// The item.
///
private void InitJobRunnerItem(JobRunnerItem item)
{
item.StartJob += () =>
{
try
{
CheckMachineOperator();
var handler = MachineOperator.Print(item.Job, item.ProcessParameters);
item.JobHandler = handler;
handler.StatusChanged += (x, status) =>
{
item.RunningJobStatus = status;
};
handler.Stopped += (x,e) =>
{
item.IsJobStarted = false;
};
}
catch (Exception ex)
{
item.IsJobStarted = false;
_notification.ShowError(ex.Message);
}
};
item.StopJob += () =>
{
if (item.JobHandler != null)
{
item.JobHandler.Cancel();
item.JobHandler = null;
}
};
}
///
/// Checks the machine operator.
///
/// No machine connected.
private void CheckMachineOperator()
{
if (MachineOperator == null || MachineOperator.State != Transport.TransportComponentState.Connected)
{
throw new InvalidOperationException("No machine connected.");
}
}
#endregion
#region Public Methods
///
/// Opens a file open dialog to select a project file.
///
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);
}
}
///
/// Opens the specified project file path.
///
/// File path.
public void OpenProjectFile(String fileName)
{
LoadProject(MachineTechViewProject.Load(fileName));
_lastTechProjectFile = fileName;
}
///
/// Loads the specified project.
///
/// The project.
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.HardwareMotorTypes.Where(x => (item as MotorGroupItem).ItemsGuids.Contains(x.Guid)).ToObservableCollection();
}
AddTechItem(item);
}
}
}
///
/// Opens the file save dialog for selecting a project file target.
///
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);
}
}
///
/// Saves the current project to the specified file path.
///
/// Name of the file.
private void SaveProjectFile(String fileName)
{
using (_notification.PushTaskItem("Saving technician project file..."))
{
MachineTechViewProject project = GenerateProjectFile();
project.Save(fileName);
_lastTechProjectFile = fileName;
}
}
///
/// Saves the current opened project file. If not project file is opened will call .
///
private void SaveProject()
{
if (File.Exists(_lastTechProjectFile))
{
SaveProjectFile(_lastTechProjectFile);
}
else
{
SaveAsProject();
}
}
///
/// Generates a project file from the current element setup.
///
///
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 IStudioModuleVM
public override void OnNavigatedTo()
{
base.OnNavigatedTo();
_singleControllers.ToList().ForEach(x => x.Value.ChangeRenderMode(true));
}
public override void OnNavigatedFrom()
{
base.OnNavigatedFrom();
_singleControllers.ToList().ForEach(x => x.Value.ChangeRenderMode(false));
}
public override void OnShuttingDown()
{
InvokeUINow(() =>
{
_settings.LastTechProjectFile = _lastTechProjectFile;
});
}
#endregion
#region Hardware Configuration
private void SyncHardwareConfiguration()
{
var elements = Elements.ToList();
if (MachineOperator != null && MachineOperator.CurrentHardwareConfiguration != null)
{
var config = MachineOperator.CurrentHardwareConfiguration;
foreach (var motorConfig in config.Motors)
{
var itemConfig = MotorItem.MotorConfigurations.SingleOrDefault(x => x.HardwareMotorType.Code == motorConfig.HardwareMotorType.ToInt32());
if (itemConfig != null)
{
motorConfig.MapPrimitivesTo(itemConfig);
}
}
foreach (var pidConfig in config.PidControls)
{
var itemConfig = PidItem.PidConfigurations.SingleOrDefault(x => x.HardwarePidControlType.Code == pidConfig.HardwarePidControlType.ToInt32());
if (itemConfig != null)
{
pidConfig.MapPrimitivesTo(itemConfig);
}
}
foreach (var winderConfig in config.Winders)
{
var itemConfig = WinderItem.WinderConfigurations.SingleOrDefault(x => x.HardwareWinderType.Code == winderConfig.HardwareWinderType.ToInt32());
if (itemConfig != null)
{
winderConfig.MapPrimitivesTo(itemConfig);
}
}
foreach (var dancerConfig in config.Dancers)
{
var itemConfig = DancerItem.DancerConfigurations.SingleOrDefault(x => x.HardwareDancerType.Code == dancerConfig.HardwareDancerType.ToInt32());
if (itemConfig != null)
{
dancerConfig.MapPrimitivesTo(itemConfig);
}
}
foreach (var speedSensorConfig in config.SpeedSensors)
{
var itemConfig = SpeedSensorItem.SpeedSensorConfigurations.SingleOrDefault(x => x.HardwareSpeedSensorType.Code == speedSensorConfig.HardwareSpeedSensorType.ToInt32());
if (itemConfig != null)
{
speedSensorConfig.MapPrimitivesTo(itemConfig);
}
}
_notification.ShowInfo("Visual elements synced to the last uploaded hardware configuration.");
}
else
{
ResetHardwareConfiguration();
}
}
private async void UploadHardwareConfiguration()
{
if (MachineOperator != null)
{
var hw = ApplicationManager.ConnectedMachine.Machine.Configuration.HardwareVersion.Clone();
foreach (var motorConfig in hw.HardwareMotors)
{
var itemConfig = MotorItem.MotorConfigurations.SingleOrDefault(x => x.HardwareMotorType.Code == motorConfig.HardwareMotorType.Code);
if (itemConfig != null)
{
itemConfig.MapPrimitivesTo(motorConfig);
}
}
foreach (var pidConfig in hw.HardwarePidControls)
{
var itemConfig = PidItem.PidConfigurations.SingleOrDefault(x => x.HardwarePidControlType.Code == pidConfig.HardwarePidControlType.Code);
if (itemConfig != null)
{
itemConfig.MapPrimitivesTo(pidConfig);
}
}
foreach (var winderConfig in hw.HardwareWinders)
{
var itemConfig = WinderItem.WinderConfigurations.SingleOrDefault(x => x.HardwareWinderType.Code == winderConfig.HardwareWinderType.Code);
if (itemConfig != null)
{
itemConfig.MapPrimitivesTo(winderConfig);
}
}
foreach (var dancerConfig in hw.HardwareDancers)
{
var itemConfig = DancerItem.DancerConfigurations.SingleOrDefault(x => x.HardwareDancerType.Code == dancerConfig.HardwareDancerType.Code);
if (itemConfig != null)
{
itemConfig.MapPrimitivesTo(dancerConfig);
}
}
foreach (var speedSensorConfig in hw.HardwareSpeedSensors)
{
var itemConfig = SpeedSensorItem.SpeedSensorConfigurations.SingleOrDefault(x => x.HardwareSpeedSensorType.Code == speedSensorConfig.HardwareSpeedSensorType.Code);
if (itemConfig != null)
{
itemConfig.MapPrimitivesTo(speedSensorConfig);
}
}
using (_notification.PushTaskItem("Uploading hardware configuration..."))
{
try
{
await MachineOperator.UploadHardwareConfiguration(hw, ApplicationManager.ConnectedMachine.Machine.Configuration);
}
catch (Exception ex)
{
LogManager.Log(ex, "Error uploading hardware configuration.");
_notification.ShowError("An error occurred while trying to upload the hardware configuration." + Environment.NewLine + ex.Message);
}
}
}
}
private void ResetHardwareConfiguration(bool showMessage = true)
{
if (MachineOperator != null)
{
var hw = ApplicationManager.ConnectedMachine.Machine.Configuration.HardwareVersion;
foreach (var motorConfig in hw.HardwareMotors)
{
var itemConfig = MotorItem.MotorConfigurations.SingleOrDefault(x => x.HardwareMotorType.Code == motorConfig.HardwareMotorType.Code);
if (itemConfig != null)
{
motorConfig.MapPrimitivesTo(itemConfig);
}
}
foreach (var pidConfig in hw.HardwarePidControls)
{
var itemConfig = PidItem.PidConfigurations.SingleOrDefault(x => x.HardwarePidControlType.Code == pidConfig.HardwarePidControlType.Code);
if (itemConfig != null)
{
pidConfig.MapPrimitivesTo(itemConfig);
}
}
foreach (var winderConfig in hw.HardwareWinders)
{
var itemConfig = WinderItem.WinderConfigurations.SingleOrDefault(x => x.HardwareWinderType.Code == winderConfig.HardwareWinderType.Code);
if (itemConfig != null)
{
winderConfig.MapPrimitivesTo(itemConfig);
}
}
foreach (var dancerConfig in hw.HardwareDancers)
{
var itemConfig = DancerItem.DancerConfigurations.SingleOrDefault(x => x.HardwareDancerType.Code == dancerConfig.HardwareDancerType.Code);
if (itemConfig != null)
{
dancerConfig.MapPrimitivesTo(itemConfig);
}
}
foreach (var speedSensorConfig in hw.HardwareSpeedSensors)
{
var itemConfig = SpeedSensorItem.SpeedSensorConfigurations.SingleOrDefault(x => x.HardwareSpeedSensorType.Code == speedSensorConfig.HardwareSpeedSensorType.Code);
if (itemConfig != null)
{
speedSensorConfig.MapPrimitivesTo(itemConfig);
}
}
if (showMessage)
{
_notification.ShowInfo("Visual elements synced to hardware version " + hw.Name + ", " + hw.Version + ".");
}
}
}
#endregion
}
}