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.ExternalBridge; 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; using Tango.MachineStudio.Technician.Models; using Tango.Logging; using Microsoft.WindowsAPICodePack.Dialogs; using RealTimeGraphX; using RealTimeGraphX.WPF.DataSeries; using RealTimeGraphX.DataPoints; using Tango.MachineStudio.Technician.Views; namespace Tango.MachineStudio.Technician.ViewModels { /// /// Represents the MachineTechView View Model. /// /// /// public class MachineTechViewVM : StudioViewModel { private List _diagnoticsMonitorsDataProperties; private IDiagnosticsFrameProvider _diagnosticsFrameProvider; 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; private List _single_graphs_recordings; private List _multi_graph_recordings; private List _single_monitors_recordings; private List _multi_monitors_recordings; private DateTime _start_time = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0); private DateTime _last_time = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0); #region Properties private ObservableCollection _tabs; /// /// Gets or sets the elements tabs. /// public ObservableCollection Tabs { get { return _tabs; } set { _tabs = value; RaisePropertyChangedAuto(); } } private MachineTechTabVM _selectedTab; /// /// Gets or sets the selected tab. /// public MachineTechTabVM SelectedTab { get { return _selectedTab; } set { _selectedTab = value; RaisePropertyChangedAuto(); foreach (var tab in Tabs.Where(x => x != _selectedTab)) { tab.IsSelected = false; } if (_selectedTab != null) { _selectedTab.IsSelected = true; } } } 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 ObservablesStaticCollections 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)); } } private int _graphsDurationSeconds; /// /// Gets or sets the graphs duration seconds. /// public int GraphsDurationSeconds { get { return _graphsDurationSeconds; } set { _graphsDurationSeconds = value; RaisePropertyChangedAuto(); } } private int _tempGraphsDurationSeconds; /// /// Gets or sets the temporary graphs duration seconds. /// public int TempGraphsDurationSeconds { get { return _tempGraphsDurationSeconds; } set { _tempGraphsDurationSeconds = value; RaisePropertyChangedAuto(); } } #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; } /// /// Gets or sets the update graphs duration command. /// public RelayCommand UpdateGraphsDurationCommand { get; set; } /// /// Gets or sets the add tab command. /// public RelayCommand AddTabCommand { get; set; } /// /// Gets or sets the remove tab command. /// public RelayCommand RemoveTabCommand { get; set; } /// /// Gets or sets the new project command. /// public RelayCommand NewProjectCommand { get; set; } /// /// Gets or sets the rename tab command. /// public RelayCommand RenameTabCommand { get; set; } /// /// Gets or sets the import project tabs command. /// /// /// The import project tabs command. /// public RelayCommand ImportProjectTabsCommand { get; set; } /// /// Gets or sets the upload partial hardware configuration command. /// public RelayCommand UploadPartialHardwareConfigurationCommand { 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) { Tabs = new ObservableCollection(); Tabs.Add(new MachineTechTabVM() { IsSelected = true, Name = "Untitled" }); SelectedTab = Tabs.First(); _settings = SettingsManager.Default.GetOrCreate(); _single_graphs_recordings = new List(); _multi_graph_recordings = new List(); _single_monitors_recordings = new List(); _multi_monitors_recordings = new List(); GraphsDurationSeconds = _settings.GraphsDuration; TempGraphsDurationSeconds = GraphsDurationSeconds; _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 = ObservablesStaticCollections.Instance; OpenProjectCommand = new RelayCommand(OpenProject); SaveAsProjectCommand = new RelayCommand(SaveAsProject); SaveProjectCommand = new RelayCommand(SaveProject); _lastTechProjectFile = _settings.LastTechProjectFile; if (File.Exists(_lastTechProjectFile)) { try { OpenProjectFile(_lastTechProjectFile); } catch (Exception ex) { LogManager.Log(ex, "Error loading last project file."); } } _diagnosticsFrameProvider = diagnosticsFrameProvider; _diagnosticsFrameProvider.FrameReceived += DiagnosticsFrameProvider_FrameReceived; UploadHardwareConfigurationCommand = new RelayCommand(UploadHardwareConfiguration); SyncHardwareConfigurationCommand = new RelayCommand(SyncHardwareConfiguration); ResetHardwareConfigurationCommand = new RelayCommand(() => ResetHardwareConfiguration()); UpdateGraphsDurationCommand = new RelayCommand(() => { GraphsDurationSeconds = TempGraphsDurationSeconds; _settings.GraphsDuration = GraphsDurationSeconds; ClearAllGraphs(); }); AddTabCommand = new RelayCommand(() => AddNewTab()); RemoveTabCommand = new RelayCommand(RemoveTab); NewProjectCommand = new RelayCommand(CreateNewProject); RenameTabCommand = new RelayCommand(RenameTab); ImportProjectTabsCommand = new RelayCommand(ImportProjectTabs); UploadPartialHardwareConfigurationCommand = new RelayCommand(UploadPartialHardwareConfiguration); } #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) { TimeSpan delta_base = DateTime.Now - _start_time; TimeSpan delta = (DateTime.Now - _last_time); double delta_mili = delta.TotalMilliseconds; _last_time = DateTime.Now; if (DateTime.Now > _lastDiagnosticsResponseUpdate.AddMilliseconds(MIN_DIAGNOSTICS_UPDATE_MILI)) { CurrentDiagnosticsResponse = data; _lastDiagnosticsResponseUpdate = DateTime.Now; CurrentDiagnosticsResponseSize = data.CalculateSize(); } foreach (var sr in _single_monitors_recordings) { var techMonitor = (sr.Tag as TechMonitor); var prop = _diagnoticsMonitorsDataProperties.SingleOrDefault(x => x.Name == techMonitor.Name); if (prop != null) { var points = GetDataArray(techMonitor, prop.GetValue(data.Monitors)); sr.PushData(points, delta_base, delta); } } foreach (var mr in _multi_monitors_recordings) { var techMonitor = (mr.Tag as TechMonitor); var prop = _diagnoticsMonitorsDataProperties.SingleOrDefault(x => x.Name == techMonitor.Name); if (prop != null) { var points = GetDataMatrix(techMonitor, prop.GetValue(data.Monitors)); mr.PushData(points, delta_base, delta); } } lock (_elementsLock) { var elements = Tabs.SelectMany(x => x.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) { TechGraphController controller = null; if (_singleControllers.TryGetValue(graphItem, out controller)) { var points = GetDataArray(graphItem.TechMonitor, prop.GetValue(data.Monitors)); List times = new List(); var dPoints = points.Select(x => new DoubleDataPoint(x)).ToList(); for (int i = 0; i < points.Count; i++) { times.Add(delta_base.Add(TimeSpan.FromMilliseconds((delta_mili / points.Count) * i))); } controller.PushData(times, dPoints); var _graph_recording = _single_graphs_recordings.SingleOrDefault(x => x.Tag == graphItem); if (_graph_recording != null) { _graph_recording.PushData(points, delta_base, delta); } } } } else if (item.GetType() == typeof(MultiGraphItem)) { MultiGraphItem graphItem = item as MultiGraphItem; var prop = _diagnoticsMonitorsDataProperties.SingleOrDefault(x => x.Name == graphItem.TechMonitor.Name); if (prop != null) { TechGraphController controller = null; if (_multiControllers.TryGetValue(graphItem, out controller)) { var points = GetDataMatrix(graphItem.TechMonitor, prop.GetValue(data.Monitors)); if (points.Count > 0) { List times = new List(); var dPoints = points.Select(x => new List(x.Select(y => new DoubleDataPoint(y)))).ToList(); for (int i = 0; i < points[0].Count; i++) { times.Add(delta_base.Add(TimeSpan.FromMilliseconds((delta_mili / points[0].Count) * i))); } List> timesMat = new List>(); for (int i = 0; i < controller.DataSeriesCollection.Count; i++) { timesMat.Add(times); } controller.PushData(timesMat, dPoints); } var _graph_recording = _multi_graph_recordings.SingleOrDefault(x => x.Tag == graphItem); if (_graph_recording != null) { _graph_recording.PushData(points, delta_base, delta); } } } } else if (item.GetType() == typeof(DigitalOutItem)) { DigitalOutItem digitalOutItem = item as DigitalOutItem; var digitalPin = data.DigitalInterfaceStates.SingleOrDefault(x => x.InterfaceIO == (InterfaceIOs)digitalOutItem.TechIo.Code); if (digitalPin != null) { digitalOutItem.EffectiveValue = digitalPin.Value; } } else if (item.GetType() == typeof(DigitalInItem)) { DigitalInItem digitalInItem = item as DigitalInItem; var digitalPin = data.DigitalInterfaceStates.SingleOrDefault(x => x.InterfaceIO == (InterfaceIOs)digitalInItem.TechIo.Code); if (digitalPin != null) { digitalInItem.Value = digitalPin.Value; } } else if (item.GetType() == typeof(HeaterItem)) { HeaterItem heaterItem = item as HeaterItem; var heaterState = data.HeatersStates.SingleOrDefault(x => x.HeaterType == (HeaterType)heaterItem.TechHeater.Code); if (heaterState != null) { heaterItem.HeaterState = heaterState; } } else if (item.GetType() == typeof(ValveItem)) { ValveItem valveItem = item as ValveItem; var valveState = data.ValvesStates.SingleOrDefault(x => x.ValveType == (ValveType)valveItem.TechValve.Code); if (valveState != null) { valveItem.EffectiveState = valveState.State; } } else if (item.GetType() == typeof(BlowerItem)) { BlowerItem blowerItem = item as BlowerItem; if (data.Monitors.BlowerVoltage.Count > 0) { blowerItem.EffectiveActive = data.Monitors.BlowerVoltage.Last() > 0; } } 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 HeaterItem) { var editor = CreateElement(bounds, Adapter.TechHeaters.FirstOrDefault()); InitTechHeater(editor.HeaterItem); } else if (item is ValveItem) { var editor = CreateElement(bounds, Adapter.TechValves.FirstOrDefault()); InitTechValveItem(editor.ValveItem); } 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 BlowerItem) { var editor = CreateElement(bounds, Adapter.HardwareBlowerTypes.FirstOrDefault()); InitBlowerItem(editor.BlowerItem); } else if (item is BreakSensorItem) { CreateElement(bounds, Adapter.HardwareBreakSensorTypes.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); } else if (item is TextItem) { CreateElement(bounds, null); } else if (item is MonitorRecorderItem) { var editor = CreateElement(bounds, null); InitMonitorRecorderItem(editor.MonitorRecorderItem); } } /// /// 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; SelectedTab.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; SelectedTab.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 HeaterItem) { (item as HeaterItem).TechHeater = Adapter.TechHeaters.FirstOrDefault(x => x.Guid == item.ItemGuid); CreateElement(item); } else if (item is ValveItem) { (item as ValveItem).TechValve = Adapter.TechValves.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 BlowerItem) { (item as BlowerItem).HardwareBlowerType = Adapter.HardwareBlowerTypes.FirstOrDefault(x => x.Guid == item.ItemGuid); var editor = CreateElement(item); InitBlowerItem(editor.BlowerItem); } else if (item is BreakSensorItem) { (item as BreakSensorItem).HardwareBreakSensorType = Adapter.HardwareBreakSensorTypes.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); } else if (item is TextItem) { CreateElement(item); } else if (item is MonitorRecorderItem) { var editor = CreateElement(item); InitMonitorRecorderItem(editor.MonitorRecorderItem); } } /// /// Called when elements have been removed /// /// The elements. public void OnElementsRemoved(List elements) { foreach (var element in elements) { if (element.HostedElement is SingleGraphItem) { var _graph_recording = _single_graphs_recordings.SingleOrDefault(x => x.Tag == element.HostedElement); if (_graph_recording != null) { (_graph_recording.Tag as SingleGraphItem).StopRecording(); _single_graphs_recordings.Remove(_graph_recording); _graph_recording.Dispose(); } } else if (element.HostedElement is MultiGraphItem) { var _graph_recording = _multi_graph_recordings.SingleOrDefault(x => x.Tag == element.HostedElement); if (_graph_recording != null) { (_graph_recording.Tag as MultiGraphItem).StopRecording(); _multi_graph_recordings.Remove(_graph_recording); _graph_recording.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; TechGraphController controller = new TechGraphController(); controller.AddDataSeries(new WpfDataSeries() { Stroke = Colors.DodgerBlue, }); editor.InnerGraph.Controller = controller; graphItem.Editor = editor; _singleControllers.Add(graphItem, controller); } else if (element is MultiGraphElementEditor) { var graphItem = element.HostedElement as MultiGraphItem; var editor = element as MultiGraphElementEditor; TechGraphController controller = new TechGraphController(500); for (int i = 0; i < graphItem.TechMonitor.ChannelCount; i++) { controller.AddDataSeries(new WpfDataSeries() { Stroke = ColorHelper.GetRandomColor(), Name = graphItem.TechMonitor.Name.First() + (i + 1).ToString(), }); } editor.InnerGraph.Controller = controller; graphItem.Editor = editor; _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 DigitalOutElementEditor) { var ioItem = element.HostedElement as DigitalOutItem; InitDigitalOutItem(ioItem); } else if (element is ThreadMotionElementEditor) { var threadMotionItem = element.HostedElement as ThreadMotionItem; InitThreadMotionItem(threadMotionItem); } else if (element is MotorGroupElementEditor) { var motorGroupItem = element.HostedElement as MotorGroupItem; InitMotorGroupItem(motorGroupItem); } else if (element is ControllerElementEditor) { var controllerItem = element.HostedElement as ControllerItem; InitControllerItem(controllerItem); } else if (element is MonitorRecorderElementEditor) { var item = element.HostedElement as MonitorRecorderItem; InitMonitorRecorderItem(item); } else if (element is ValveElementEditor) { var item = element.HostedElement as ValveItem; InitTechValveItem(item); } else if (element is BlowerElementEditor) { var item = element.HostedElement as BlowerItem; InitBlowerItem(item); } else if (element is HeaterElementEditor) { var item = element.HostedElement as HeaterItem; InitTechHeater(item); } else if (element is ProcessParametersElementEditor) { var item = element.HostedElement as ProcessParametersItem; InitProcessParameterItem(item); } } } #endregion #region Init Tech Items /// /// Initializes the monitor recorder item. /// /// The item. private void InitMonitorRecorderItem(MonitorRecorderItem item) { item.RecordingStarted += () => { CommonOpenFileDialog dlg = new CommonOpenFileDialog(); dlg.Title = "Select a folder to place all CSV files."; dlg.IsFolderPicker = true; if (dlg.ShowDialog() == CommonFileDialogResult.Ok) { foreach (var monitor in item.GetSelectedMonitors()) { if (!monitor.MultiChannel) { _single_monitors_recordings.Add(new SingleTechRecordingData(monitor.Description, dlg.FileName + "\\" + monitor.Description + ".csv") { Tag = monitor }); } else { _multi_monitors_recordings.Add(new MultiTechRecordingData(monitor.Description, monitor.ChannelCount, dlg.FileName + "\\" + monitor.Description + ".csv") { Tag = monitor }); } item.StartRecording(); } } }; item.RecordingStopped += () => { item.StopRecording(); foreach (var sr in _single_monitors_recordings) { sr.Dispose(); } _single_monitors_recordings.Clear(); foreach (var mr in _multi_monitors_recordings) { mr.Dispose(); } _multi_monitors_recordings.Clear(); }; } /// /// Initializes the tech valve. /// /// The valve item. private void InitTechValveItem(ValveItem item) { item.StateChanged += async (x, state) => { try { CheckMachineOperator(); await MachineOperator.SetValveState((ValveType)item.TechValve.Code, state); } catch (Exception ex) { LogManager.Log(ex, String.Format("Error executing technician set valve state command on '{0}'.", item.TechName)); _eventLogger.Log(ex, String.Format("Error executing technician set valve state command on '{0}'.", item.TechName)); } }; } /// /// Initializes the blower item. /// /// The blower item. private void InitBlowerItem(BlowerItem item) { item.SetCommandClicked += async (_, isActive) => { try { CheckMachineOperator(); await MachineOperator.SetBlowerState((PMR.Hardware.HardwareBlowerType)item.HardwareBlower.HardwareBlowerType.Code, isActive, item.HardwareBlower.Voltage); } catch (Exception ex) { LogManager.Log(ex, $"Error executing SetBlowerState command for blower {item.HardwareBlower.HardwareBlowerType.Name}."); _eventLogger.Log(ex, $"Error executing SetBlowerState command for blower {item.HardwareBlower.HardwareBlowerType.Name}."); } }; } /// /// Initializes the tech heater. /// /// The item. private void InitTechHeater(HeaterItem item) { item.SetCommandClicked += async () => { try { CheckMachineOperator(); await MachineOperator.SetHeaterState((HeaterType)item.TechHeater.Code, item.SetPoint); } catch (Exception ex) { LogManager.Log(ex, $"Error executing SetHeaterState command for heater {item.TechHeater.Name}."); _eventLogger.Log(ex, $"Error executing SetHeaterState command for heater {item.TechHeater.Name}."); } }; } /// /// 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() { MotorType = (PMR.Hardware.HardwareMotorType)item.HardwareMotorType.Code, Speed = item.Speed, Direction = MotorDirection.Forward, }); } else if (action == MotorActionType.ForwardReleased) { await MachineOperator.StopMotorJogging(new MotorAbortJoggingRequest() { MotorType = (PMR.Hardware.HardwareMotorType)item.HardwareMotorType.Code, }); } else if (action == MotorActionType.BackwardPressed) { await MachineOperator.StartMotorJogging(new MotorJoggingRequest() { MotorType = (PMR.Hardware.HardwareMotorType)item.HardwareMotorType.Code, Speed = item.Speed, Direction = MotorDirection.Backward, }); } else if (action == MotorActionType.BackwardReleased) { await MachineOperator.StopMotorJogging(new MotorAbortJoggingRequest() { MotorType = (PMR.Hardware.HardwareMotorType)item.HardwareMotorType.Code, }); } else if (action == MotorActionType.HomingForwardStarted || action == MotorActionType.HomingBackwardStarted) { item.HomingProgress = 0; item.IsHoming = true; item.IsHomingCompleted = false; MachineOperator.StartMotorHoming(new MotorHomingRequest() { MotorType = (PMR.Hardware.HardwareMotorType)item.HardwareMotorType.Code, Speed = item.Speed, Direction = action == MotorActionType.HomingBackwardStarted ? MotorDirection.Backward : MotorDirection.Forward }) .Subscribe((response) => { item.HomingMaximumProgress = response.MaxProgress; item.HomingProgress = response.Progress; }, (ex) => { item.IsHoming = false; item.IsHomingCompleted = true; }, () => { item.IsHoming = false; item.IsHomingCompleted = true; }); } else if (action == MotorActionType.HomingStopped) { await MachineOperator.StopMotorHoming(new MotorAbortHomingRequest() { MotorType = (PMR.Hardware.HardwareMotorType)item.HardwareMotorType.Code, }); item.IsHoming = false; } } catch (Exception ex) { item.IsHomingCompleted = true; item.IsHoming = false; item.HomingProgress = 0; item.HomingMaximumProgress = 0; 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() { Index = item.TechDispenser.Code, Direction = MotorDirection.Forward, Speed = item.Speed, }); } else if (action == MotorActionType.ForwardReleased) { await MachineOperator.StopDispenserJogging(new DispenserAbortJoggingRequest() { Index = item.TechDispenser.Code, }); } else if (action == MotorActionType.BackwardPressed) { await MachineOperator.StartDispenserJogging(new DispenserJoggingRequest() { Index = item.TechDispenser.Code, Direction = MotorDirection.Backward, Speed = item.Speed, }); } else if (action == MotorActionType.BackwardReleased) { await MachineOperator.StopDispenserJogging(new DispenserAbortJoggingRequest() { Index = item.TechDispenser.Code, }); } else if (action == MotorActionType.HomingForwardStarted || action == MotorActionType.HomingBackwardStarted) { item.HomingProgress = 0; item.IsHoming = true; item.IsHomingCompleted = false; MachineOperator.StartDispenserHoming(new DispenserHomingRequest() { Index = item.TechDispenser.Code, Speed = item.Speed, Direction = action == MotorActionType.HomingBackwardStarted ? MotorDirection.Backward : MotorDirection.Forward }) .Subscribe((response) => { item.HomingMaximumProgress = response.MaxProgress; item.HomingProgress = response.Progress; }, (ex) => { item.IsHoming = false; item.IsHomingCompleted = true; }, () => { item.IsHoming = false; item.IsHomingCompleted = true; }); } else if (action == MotorActionType.HomingStopped) { await MachineOperator.StopDispenserHoming(new DispenserAbortHomingRequest() { Index = item.TechDispenser.Code, }); item.IsHoming = false; } } catch (Exception ex) { item.IsHomingCompleted = true; item.IsHoming = false; item.HomingProgress = 0; item.HomingMaximumProgress = 0; 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) { TechGraphController controller = new TechGraphController(); controller.Range.AutoY = true; controller.Range.MinimumY = item.TechMonitor.Min; controller.Range.MaximumY = item.TechMonitor.Max; controller.Range.MaximumX = TimeSpan.FromSeconds(10); controller.AddDataSeries(new WpfDataSeries() { Stroke = Colors.DodgerBlue, }); editor.InnerGraph.Controller = controller; item.Editor = editor; _singleControllers.Add(item, controller); item.RecordingStarted += () => { SaveFileDialog dlg = new SaveFileDialog(); dlg.Title = "Save graph data as csv file"; dlg.Filter = "CSV Files|*.csv"; dlg.DefaultExt = ".csv"; dlg.FileName = item.TechName; if (dlg.ShowDialog().Value) { _single_graphs_recordings.Add(new SingleTechRecordingData(item.TechName, dlg.FileName) { Tag = item }); item.StartRecording(); } }; item.RecordingStopped += () => { try { item.StopRecording(); var graph_recording = _single_graphs_recordings.SingleOrDefault(x => x.Tag == item); if (graph_recording != null) { _single_graphs_recordings.Remove(graph_recording); graph_recording.Dispose(); } } catch (Exception ex) { _notification.ShowError(LogManager.Log(ex).Message); } }; } /// /// Initializes the multi graph item. /// /// The item. /// The editor. private void InitMultiGraphItem(MultiGraphItem item, MultiGraphElementEditor editor) { TechGraphController controller = new TechGraphController(500); controller.Range.AutoY = true; controller.Range.MinimumY = item.TechMonitor.Min; controller.Range.MaximumY = item.TechMonitor.Max; controller.Range.MaximumX = TimeSpan.FromSeconds(10); for (int i = 0; i < item.TechMonitor.ChannelCount; i++) { controller.AddDataSeries(new WpfDataSeries() { Stroke = ColorHelper.GetRandomColor(), Name = item.TechMonitor.Name.First() + (i + 1).ToString(), }); } editor.InnerGraph.Controller = controller; item.Editor = editor; _multiControllers.Add(item, controller); item.RecordingStarted += () => { SaveFileDialog dlg = new SaveFileDialog(); dlg.Title = "Save graph data as csv file"; dlg.Filter = "CSV Files|*.csv"; dlg.DefaultExt = ".csv"; dlg.FileName = item.TechName; if (dlg.ShowDialog().Value) { _multi_graph_recordings.Add(new MultiTechRecordingData(item.TechName, item.TechMonitor.ChannelCount, dlg.FileName) { Tag = item }); item.StartRecording(); } }; item.RecordingStopped += () => { try { item.StopRecording(); var graph_recording = _multi_graph_recordings.SingleOrDefault(x => x.Tag == item); if (graph_recording != null) { _multi_graph_recordings.Remove(graph_recording); graph_recording.Dispose(); } } catch (Exception ex) { _notification.ShowError(LogManager.Log(ex).Message); } }; } /// /// 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() { Speed = item.Speed, }); } 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() { MotorType = (PMR.Hardware.HardwareMotorType)motor.Code, Direction = MotorDirection.Forward, }))); } else if (action == MotorActionType.ForwardReleased) { await Task.WhenAll(item.TechMotors.Select(motor => MachineOperator.StopMotorJogging(new MotorAbortJoggingRequest() { MotorType = (PMR.Hardware.HardwareMotorType)motor.Code, }))); } else if (action == MotorActionType.BackwardPressed) { await Task.WhenAll(item.TechMotors.Select(motor => MachineOperator.StartMotorJogging(new MotorJoggingRequest() { MotorType = (PMR.Hardware.HardwareMotorType)motor.Code, Direction = MotorDirection.Backward, }))); } else if (action == MotorActionType.BackwardReleased) { await Task.WhenAll(item.TechMotors.Select(motor => MachineOperator.StopMotorJogging(new MotorAbortJoggingRequest() { MotorType = (PMR.Hardware.HardwareMotorType)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() { InterfaceIO = (InterfaceIOs)item.TechIo.Code, 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.SetCommandClicked += async (_, __) => { try { CheckMachineOperator(); await MachineOperator.SetComponentValue(new SetComponentValueRequest() { Component = (ValueComponent)item.TechController.Code, Value = item.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 Project Management /// /// 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 MachineTechViewProject OpenProjectFile(String fileName, bool load = true) { MachineTechViewProject project = null; try { project = MachineTechViewProject.Load(fileName); if (project.Tabs.Count == 0) { LogManager.Log($"Error loading project file {fileName}. Trying to load using legacy project loader.", LogCategory.Warning); MachineTechViewProjectTab tab = new MachineTechViewProjectTab(); tab.Name = "Untitled"; tab.Items.AddRange(project.Items); project.Items.Clear(); project.Tabs.Add(tab); } if (load) { LoadProject(project); _lastTechProjectFile = fileName; } } catch (Exception ex) { LogManager.Log(ex, $"Error loading project file {fileName}."); _notification.ShowError("An error occurred while trying to load the tech board project file."); } return project; } /// /// Loads the specified project. /// /// The project. public void LoadProject(MachineTechViewProject project, bool appendToCurrentProject = false) { using (_notification.PushTaskItem("Loading technician project file...")) { if (!appendToCurrentProject) { Tabs.Clear(); _singleControllers.Clear(); _multiControllers.Clear(); } foreach (var tab in project.Tabs) { MachineTechTabVM t = new MachineTechTabVM(); t.Name = tab.Name; Tabs.Add(t); SelectedTab = t; foreach (var item in tab.Items) { if (item is MotorGroupItem) { (item as MotorGroupItem).TechMotors = ObservablesStaticCollections.Instance.HardwareMotorTypes.Where(x => (item as MotorGroupItem).ItemsGuids.Contains(x.Guid)).ToObservableCollection(); } else if (item is MonitorRecorderItem) { (item as MonitorRecorderItem).SetSelectedMonitors(ObservablesStaticCollections.Instance.TechMonitors.Where(x => (item as MonitorRecorderItem).SelectedMonitorsGuids.Contains(x.Guid)).ToList()); } AddTechItem(item); } } SelectedTab = Tabs.ElementAt(project.SelectedTabIndex); } } /// /// 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(); project.SelectedTabIndex = Tabs.IndexOf(SelectedTab); foreach (var tab in Tabs) { MachineTechViewProjectTab pTab = new MachineTechViewProjectTab(); pTab.Name = tab.Name; foreach (var element in tab.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()); pTab.Items.Add(element.HostedElement as TechItem); } project.Tabs.Add(pTab); } return project; } /// /// Removes the specified tab. /// /// The tab. private void RemoveTab(MachineTechTabVM tab) { if (_notification.ShowQuestion("Are you sure you want to delete the selected tab?")) { Tabs.Remove(tab); SelectedTab = Tabs.LastOrDefault(); if (SelectedTab == null) { AddNewTab("Untitled"); } } } /// /// Adds a new tab. /// private bool AddNewTab(String name = null) { if (Tabs.Count > 7) { _notification.ShowError("Cannot exceed the maximum number of 8 tabs. You can remove a tab, or create a new project."); return false; } if (name == null) { name = _notification.ShowTextInput("Enter tab name", "Tab Name", "Untitled"); } if (!String.IsNullOrWhiteSpace(name)) { MachineTechTabVM t = new MachineTechTabVM(); t.Name = name; Tabs.Add(t); SelectedTab = t; return true; } else { return false; } } /// /// Creates a new project. /// private void CreateNewProject() { var to_remove = Tabs.ToList(); if (AddNewTab()) { _singleControllers.Clear(); _multiControllers.Clear(); foreach (var tab in to_remove) { Tabs.Remove(tab); } } } /// /// Renames the tab. /// /// The tab. private void RenameTab() { if (SelectedTab != null) { var name = _notification.ShowTextInput("Enter tab name", "Tab Name", SelectedTab.Name); if (!String.IsNullOrWhiteSpace(name)) { SelectedTab.Name = name; } } } /// /// Imports a project file tabs to the current project. /// private void ImportProjectTabs() { OpenFileDialog dlg = new OpenFileDialog(); dlg.Title = "Select Technician Project File"; dlg.Filter = "Technician Project File|*.tpf"; if (dlg.ShowDialog().Value) { var project = OpenProjectFile(dlg.FileName, false); if (project != null) { var vm = new ImportProjectTabViewVM(project.Tabs, Path.GetFileNameWithoutExtension(dlg.FileName)); _notification.ShowModalDialog(vm, (x) => { project.Tabs.Clear(); project.Tabs.AddRange(vm.Tabs.SynchedSource.ToList()); LoadProject(project, true); }, () => { }); } } } #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; }); } public override void OnApplicationReady() { } #endregion #region Hardware Configuration private void SyncHardwareConfiguration() { var elements = Tabs.SelectMany(x => x.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); } } foreach (var blowerConfig in config.Blowers) { var itemConfig = BlowerItem.BlowerConfigurations.SingleOrDefault(x => x.HardwareBlowerType.Code == blowerConfig.HardwareBlowerType.ToInt32()); if (itemConfig != null) { blowerConfig.MapPrimitivesTo(itemConfig); } } foreach (var breakSensorConfig in config.BreakSensors) { var itemConfig = BreakSensorItem.BreakSensorConfigurations.SingleOrDefault(x => x.HardwareBreakSensorType.Code == breakSensorConfig.HardwareBreakSensorType.ToInt32()); if (itemConfig != null) { breakSensorConfig.MapPrimitivesTo(itemConfig); } } _notification.ShowInfo("Visual elements synced to the last uploaded hardware configuration."); } else { ResetHardwareConfiguration(); } } private async void UploadHardwareConfiguration() { if (MachineOperator != null) { using (_notification.PushTaskItem("Uploading hardware configuration...")) { try { HardwareVersion hw = null; Configuration config = null; await Task.Factory.StartNew(() => { using (ObservablesContext db = ObservablesContext.CreateDefault()) { config = db.Adapter.GetConfiguration(x => x.Guid == ApplicationManager.Machine.ConfigurationGuid).Clone(); hw = db.Adapter.GetHardwareVersionByMachine(ApplicationManager.Machine.Guid).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); } } foreach (var blowerConfig in hw.HardwareBlowers) { var itemConfig = BlowerItem.BlowerConfigurations.SingleOrDefault(x => x.HardwareBlowerType.Code == blowerConfig.HardwareBlowerType.Code); if (itemConfig != null) { itemConfig.MapPrimitivesTo(blowerConfig); } } foreach (var breakSensorConfig in hw.HardwareBreakSensors) { var itemConfig = BreakSensorItem.BreakSensorConfigurations.SingleOrDefault(x => x.HardwareBreakSensorType.Code == breakSensorConfig.HardwareBreakSensorType.Code); if (itemConfig != null) { itemConfig.MapPrimitivesTo(breakSensorConfig); } } await MachineOperator.UploadHardwareConfiguration(hw, config); } 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 async void UploadPartialHardwareConfiguration() { if (MachineOperator != null) { if (_notification.ShowQuestion("This will upload only visible elements across all tabs as a hardware configuration package. Are you sure?")) { using (_notification.PushTaskItem("Uploading partial hardware configuration...")) { try { HardwareVersion hw = new HardwareVersion(); hw.Name = "Partial HW Configuration"; hw.Version = 1; Configuration config = null; foreach (var element in Tabs.SelectMany(x => x.Elements).ToList()) { var item = element.HostedElement as TechItem; if (item is MotorItem) { hw.HardwareMotors.Add((item as MotorItem).HardwareMotor); } else if (item is DancerItem) { hw.HardwareDancers.Add((item as DancerItem).HardwareDancer); } else if (item is PidItem) { hw.HardwarePidControls.Add((item as PidItem).HardwarePid); } else if (item is BlowerItem) { hw.HardwareBlowers.Add((item as BlowerItem).HardwareBlower); } else if (item is BreakSensorItem) { hw.HardwareBreakSensors.Add((item as BreakSensorItem).HardwareBreakSensor); } else if (item is SpeedSensorItem) { hw.HardwareSpeedSensors.Add((item as SpeedSensorItem).HardwareSpeedSensor); } else if (item is WinderItem) { hw.HardwareWinders.Add((item as WinderItem).HardwareWinder); } } await Task.Factory.StartNew(() => { using (ObservablesContext db = ObservablesContext.CreateDefault()) { config = db.Adapter.GetConfiguration(x => x.Guid == ApplicationManager.Machine.ConfigurationGuid).Clone(); } }); await MachineOperator.UploadHardwareConfiguration(hw, config); } catch (Exception ex) { LogManager.Log(ex, "Error uploading partial hardware configuration."); _notification.ShowError("An error occurred while trying to upload the partial hardware configuration." + Environment.NewLine + ex.Message); } } } } } private async void ResetHardwareConfiguration(bool showMessage = true) { if (MachineOperator != null) { ObservablesContext db = ObservablesContext.CreateDefault(); ObservablesContextAdapter adapter = new ObservablesContextAdapter(db); HardwareVersion hw = null; await Task.Factory.StartNew(() => { hw = adapter.GetHardwareVersionByMachine(ApplicationManager.Machine.Guid); }); 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); } } foreach (var blowerSensorConfig in hw.HardwareBlowers) { var itemConfig = BlowerItem.BlowerConfigurations.SingleOrDefault(x => x.HardwareBlowerType.Code == blowerSensorConfig.HardwareBlowerType.Code); if (itemConfig != null) { blowerSensorConfig.MapPrimitivesTo(itemConfig); } } foreach (var breakSensorConfig in hw.HardwareBreakSensors) { var itemConfig = BreakSensorItem.BreakSensorConfigurations.SingleOrDefault(x => x.HardwareBreakSensorType.Code == breakSensorConfig.HardwareBreakSensorType.Code); if (itemConfig != null) { breakSensorConfig.MapPrimitivesTo(itemConfig); } } if (showMessage) { _notification.ShowInfo("Visual elements synced to hardware version " + hw.Name + ", " + hw.Version + "."); } } } #endregion #region Graphs public void ClearAllGraphs() { foreach (var controller in _singleControllers) { controller.Value.Clear(); } foreach (var controller in _multiControllers) { controller.Value.Clear(); } } #endregion } }