using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using Tango.Core.Commands;
using Tango.Core.Helpers;
using Tango.BL.Entities;
using Tango.MachineStudio.Common.Notifications;
using Tango.SharedUI;
using SimpleValidator.Extensions;
using Tango.MachineStudio.Common.StudioApplication;
using Tango.MachineStudio.Common;
using Tango.BL;
using Tango.AutoComplete.Editors;
using System.Data.Entity;
using Tango.BL.Builders;
using Tango.MachineStudio.MachineDesigner.Contracts;
using System.Windows.Threading;
using Tango.Core.Threading;
using Tango.MachineStudio.RML.ViewModels;
using Tango.Settings;
using Tango.MachineStudio.RML.Models;
using Tango.BL.ActionLogs;
using Tango.MachineStudio.Common.Authentication;
using Tango.BL.DTO;
using Tango.Core.Cryptography;
using Tango.BL.Enumerations;
using Tango.MachineStudio.MachineDesigner.Models;
namespace Tango.MachineStudio.MachineDesigner.ViewModels
{
public class MainViewVM : StudioViewModel<IMainView>
{
private INotificationProvider _notification;
private IActionLogManager _actionLogManager;
private IAuthenticationProvider _authentication;
private ActionTimer _machines_action_timer;
private ActionTimer _dispensers_action_timer;
private MachineDTO _machineBeforeSave;
private List<Site> _all_sites;
#region Properties
private bool _isNewMachine;
public bool IsNewMachine
{
get { return _isNewMachine; }
set { _isNewMachine = value; RaisePropertyChangedAuto(); }
}
private ObservablesStaticCollections _activeMachineAdapter;
public ObservablesStaticCollections ActiveMachineAdapter
{
get { return _activeMachineAdapter; }
set { _activeMachineAdapter = value; RaisePropertyChangedAuto(); }
}
private List<MachineModel> _machines;
/// <summary>
/// Gets or sets the available filtered machines.
/// </summary>
public List<MachineModel> Machines
{
get { return _machines; }
set { _machines = value; RaisePropertyChangedAuto(); }
}
private MachineModel _selectedMachine;
/// <summary>
/// Gets or sets the selected machine from the drop down.
/// </summary>
public MachineModel SelectedMachine
{
get { return _selectedMachine; }
set
{
if (_selectedMachine != value)
{
_selectedMachine = value;
RaisePropertyChangedAuto();
InvalidateRelayCommands();
}
}
}
private Machine _activeMachine;
/// <summary>
/// Gets or sets the active machine.
/// </summary>
public Machine ActiveMachine
{
get { return _activeMachine; }
set { _activeMachine = value; RaisePropertyChangedAuto(); }
}
private IdsPack _selectedIds;
/// <summary>
/// Gets or sets the selected ids pack.
/// </summary>
public IdsPack SelectedIds
{
get { return _selectedIds; }
set { _selectedIds = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
}
private String _dispensersFilter;
/// <summary>
/// Gets or sets the dispensers filter.
/// </summary>
public String DispensersFilter
{
get { return _dispensersFilter; }
set { _dispensersFilter = value; RaisePropertyChangedAuto(); OnDispensersFilterChanged(); }
}
private String _filter;
/// <summary>
/// Gets or sets the machines filter.
/// </summary>
public String Filter
{
get { return _filter; }
set { _filter = value; RaisePropertyChangedAuto(); OnFilterChanged(); }
}
private Spool _selectedSpool;
public Spool SelectedSpool
{
get { return _selectedSpool; }
set { _selectedSpool = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
}
private Site _selectedSite;
public Site SelectedSite
{
get { return _selectedSite; }
set { _selectedSite = value; RaisePropertyChangedAuto(); }
}
private List<Site> _sites;
public List<Site> Sites
{
get { return _sites; }
set { _sites = value; RaisePropertyChangedAuto(); }
}
private bool _isGen1Machine;
public bool IsGen1Machine
{
get { return _isGen1Machine; }
set { _isGen1Machine = value; RaisePropertyChangedAuto(); }
}
private ColorCalibrationViewVM _colorCalibrationViewVM;
public ColorCalibrationViewVM ColorCalibrationViewVM
{
get { return _colorCalibrationViewVM; }
set { _colorCalibrationViewVM = value; RaisePropertyChangedAuto(); }
}
private HardwareConfigurationViewVM _hardwareConfigurationViewVM;
public HardwareConfigurationViewVM HardwareConfigurationViewVM
{
get { return _hardwareConfigurationViewVM; }
set
{
_hardwareConfigurationViewVM = value;
RaisePropertyChangedAuto();
}
}
private MachineUpdatesViewVM _machineUpdatesViewVM;
public MachineUpdatesViewVM MachineUpdatesViewVM
{
get { return _machineUpdatesViewVM; }
set { _machineUpdatesViewVM = value; RaisePropertyChangedAuto(); }
}
private TupViewVM _tupViewVM;
public TupViewVM TupViewVM
{
get { return _tupViewVM; }
set { _tupViewVM = value; RaisePropertyChangedAuto(); }
}
#endregion
#region Commands
/// <summary>
/// Gets or sets the save command.
/// </summary>
public RelayCommand SaveCommand { get; set; }
/// <summary>
/// Gets or sets the add ids command.
/// </summary>
public RelayCommand AddIdsCommand { get; set; }
/// <summary>
/// Gets or sets the remove ids command.
/// </summary>
public RelayCommand RemoveIdsCommand { get; set; }
/// <summary>
/// Gets or sets the remove machine command.
/// </summary>
public RelayCommand RemoveMachineCommand { get; set; }
/// <summary>
/// Gets or sets the add machine command.
/// </summary>
public RelayCommand AddMachineCommand { get; set; }
/// <summary>
/// Gets or sets the edit machine command.
/// </summary>
public RelayCommand EditMachineCommand { get; set; }
/// <summary>
/// Gets or sets the back to machines command.
/// </summary>
public RelayCommand BackToMachinesCommand { get; set; }
/// <summary>
/// Gets or sets the add spool command.
/// </summary>
public RelayCommand AddSpoolCommand { get; set; }
/// <summary>
/// Gets or sets the remove spool command.
/// </summary>
public RelayCommand RemoveSpoolCommand { get; set; }
/// <summary>
/// Gets or sets the clone machine command.
/// </summary>
public RelayCommand CloneMachineCommand { get; set; }
/// <summary>
/// Gets or sets the reset device registration command.
/// </summary>
public RelayCommand ResetDeviceRegistrationCommand { get; set; }
/// <summary>
/// Gets or sets the make prototype command.
/// </summary>
public RelayCommand MakePrototypeCommand { get; set; }
public RelayCommand UpgradeToGen2Command { get; set; }
#endregion
#region Constructors
public MainViewVM()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MainViewVM"/> class.
/// </summary>
public MainViewVM(INotificationProvider notification, IAuthenticationProvider authentication, IActionLogManager actionLogManager)
{
_notification = notification;
_authentication = authentication;
_actionLogManager = actionLogManager;
Machines = new List<MachineModel>();
_machines_action_timer = new ActionTimer(TimeSpan.FromMilliseconds(200));
_dispensers_action_timer = new ActionTimer(TimeSpan.FromMilliseconds(200));
AddIdsCommand = new RelayCommand(AddIds, (x) => ActiveMachine != null && ActiveMachine.Configuration != null && ActiveMachine.Configuration.IdsPacks.Count < 10);
RemoveIdsCommand = new RelayCommand(RemoveIds, (x) => SelectedIds != null);
EditMachineCommand = new RelayCommand(() => LoadSelectedMachine(), () => SelectedMachine != null);
BackToMachinesCommand = new RelayCommand(() => View.NavigateTo(MachineDesignerNavigationView.MachinesView));
SaveCommand = new RelayCommand(SaveMachine);
AddMachineCommand = new RelayCommand(AddNewMachine);
RemoveMachineCommand = new RelayCommand(RemoveSelectedMachine, () => SelectedMachine != null);
AddSpoolCommand = new RelayCommand(AddNewSpool);
RemoveSpoolCommand = new RelayCommand(RemoveSpool, () => SelectedSpool != null);
CloneMachineCommand = new RelayCommand(CloneMachine, () => SelectedMachine != null);
ResetDeviceRegistrationCommand = new RelayCommand(ResetDeviceRegistration);
MakePrototypeCommand = new RelayCommand(MakePrototype);
MachineUpdatesViewVM = new MachineUpdatesViewVM(_notification);
TupViewVM = new TupViewVM(_notification);
UpgradeToGen2Command = new RelayCommand(UpgradeToGEN2);
}
#endregion
public override void OnApplicationReady()
{
}
private void OnDispensersFilterChanged()
{
if (!String.IsNullOrWhiteSpace(DispensersFilter))
{
_dispensers_action_timer.ResetReplace(() =>
{
Task.Factory.StartNew(() =>
{
ActiveMachineAdapter.Dispensers = ActiveMachineAdapter.Context.Dispensers.Where(x => x.SerialNumber.ToLower().StartsWith(DispensersFilter.ToLower())).OrderBy(x => x.SerialNumber).ToSynchronizedObservableCollection();
});
});
}
}
#region Drag Drop Handlers
/// <summary>
/// Drops the ids pack.
/// </summary>
/// <param name="idsPack1">The ids pack1.</param>
/// <param name="idsPack2">The ids pack2.</param>
public void DropIdsPack(IdsPack idsPack1, IdsPack idsPack2)
{
ActiveMachine.Configuration.IdsPacks.Swap(idsPack1, idsPack2);
ColorCalibrationViewVM.InvalidateCalibrationDataAndColorConversion();
}
/// <summary>
/// Drops the touch panel.
/// </summary>
/// <param name="applicationDisplayPanelVersion">The application display panel version.</param>
public void DropTouchPanel(ApplicationDisplayPanelVersion applicationDisplayPanelVersion)
{
ActiveMachine.Configuration.ApplicationDisplayPanelVersion = applicationDisplayPanelVersion;
ActiveMachine.Configuration.ApplicationDisplayPanelVersionGuid = applicationDisplayPanelVersion.Guid;
}
/// <summary>
/// Drops the application firmware version.
/// </summary>
/// <param name="applicationFirmwareVersion">The application firmware version.</param>
public void DropApplicationFirmwareVersion(ApplicationFirmwareVersion applicationFirmwareVersion)
{
ActiveMachine.Configuration.ApplicationFirmwareVersion = applicationFirmwareVersion;
ActiveMachine.Configuration.ApplicationFirmwareVersionGuid = applicationFirmwareVersion.Guid;
}
/// <summary>
/// Drops the hardware version.
/// </summary>
/// <param name="hardwareVersion">The hardware version.</param>
public void DropHardwareVersion(HardwareVersion hardwareVersion)
{
ActiveMachine.Configuration.HardwareVersion = hardwareVersion;
ActiveMachine.Configuration.HardwareVersionGuid = hardwareVersion.Guid;
}
/// <summary>
/// Drops the embedded firmware.
/// </summary>
/// <param name="embeddedFirmwareVersion">The embedded firmware version.</param>
public void DropEmbeddedFirmware(EmbeddedFirmwareVersion embeddedFirmwareVersion)
{
ActiveMachine.Configuration.EmbeddedFirmwareVersion = embeddedFirmwareVersion;
ActiveMachine.Configuration.EmbeddedFirmwareVersionGuid = embeddedFirmwareVersion.Guid;
}
/// <summary>
/// Drops the application os version.
/// </summary>
/// <param name="applicationOsVersion">The application os version.</param>
public void DropApplicationOsVersion(ApplicationOsVersion applicationOsVersion)
{
ActiveMachine.Configuration.ApplicationOsVersion = applicationOsVersion;
ActiveMachine.Configuration.ApplicationOsVersionGuid = applicationOsVersion.Guid;
}
/// <summary>
/// Drops the dispenser.
/// </summary>
/// <param name="dispenser">The dispenser.</param>
/// <param name="idsPack">The ids pack.</param>
public void DropDispenser(Dispenser dispenser, IdsPack idsPack)
{
idsPack.Dispenser = dispenser;
idsPack.DispenserGuid = dispenser.Guid;
}
/// <summary>
/// Drops the type of the cartridge.
/// </summary>
/// <param name="cartridgeType">Type of the cartridge.</param>
/// <param name="idsPack">The ids pack.</param>
public void DropCartridgeType(CartridgeType cartridgeType, IdsPack idsPack)
{
idsPack.CartridgeType = cartridgeType;
idsPack.CartridgeTypeGuid = cartridgeType.Guid;
}
/// <summary>
/// Drops the type of the mid tank.
/// </summary>
/// <param name="midTankType">Type of the mid tank.</param>
/// <param name="idsPack">The ids pack.</param>
public void DropMidTankType(MidTankType midTankType, IdsPack idsPack)
{
idsPack.MidTankType = midTankType;
idsPack.MidTankTypeGuid = midTankType.Guid;
}
/// <summary>
/// Drops the type of the liquid.
/// </summary>
/// <param name="liquidType">Type of the liquid.</param>
/// <param name="idsPack">The ids pack.</param>
public void DropLiquidType(LiquidType liquidType, IdsPack idsPack)
{
idsPack.LiquidType = liquidType;
idsPack.LiquidTypeGuid = liquidType.Guid;
ColorCalibrationViewVM.InvalidateCalibrationDataAndColorConversion();
}
/// <summary>
/// Drops the ids formula.
/// </summary>
/// <param name="idsPackFormula">The ids pack formula.</param>
/// <param name="idsPack">The ids pack.</param>
/// <exception cref="NotImplementedException"></exception>
public void DropIdsFormula(IdsPackFormula idsPackFormula, IdsPack idsPack)
{
idsPack.IdsPackFormula = idsPackFormula;
idsPack.IdsPackFormulaGuid = idsPackFormula.Guid;
}
#endregion
#region Private Methods
/// <summary>
/// Removes the selected IDS pack.
/// </summary>
private void RemoveIds()
{
ActiveMachineAdapter.Context.IdsPacks.Remove(SelectedIds);
SelectedIds = null;
ColorCalibrationViewVM.InvalidateCalibrationDataAndColorConversion();
}
/// <summary>
/// Adds a new IDS pack.
/// </summary>
private void AddIds()
{
ActiveMachineAdapter.Context.IdsPacks.Add(new IdsPack() { Configuration = ActiveMachine.Configuration });
InvalidateRelayCommands();
}
private async void LoadSelectedMachine(bool newMachine = false, bool clone = false, MachineCreationDialogVM machineCreationDialogVM = null)
{
IsNewMachine = false;
using (_notification.PushTaskItem("Loading machine details..."))
{
try
{
IsFree = false;
if (ActiveMachineAdapter != null)
{
ActiveMachineAdapter.Context.Dispose();
}
ActiveMachineAdapter = new ObservablesStaticCollections(ObservablesContext.CreateDefault());
ActiveMachineAdapter.Organizations = (await ActiveMachineAdapter.Context.Organizations.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.MachineVersions = (await ActiveMachineAdapter.Context.MachineVersions.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.Rmls = (await ActiveMachineAdapter.Context.Rmls.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.ColorSpaces = (await ActiveMachineAdapter.Context.ColorSpaces.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.SpoolTypes = (await ActiveMachineAdapter.Context.SpoolTypes.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.ApplicationDisplayPanelVersions = (await ActiveMachineAdapter.Context.ApplicationDisplayPanelVersions.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.ApplicationFirmwareVersions = (await ActiveMachineAdapter.Context.ApplicationFirmwareVersions.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.ApplicationOsVersions = (await ActiveMachineAdapter.Context.ApplicationOsVersions.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.EmbeddedFirmwareVersions = (await ActiveMachineAdapter.Context.EmbeddedFirmwareVersions.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.DispenserTypes = (await ActiveMachineAdapter.Context.DispenserTypes.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.LiquidTypes = (await ActiveMachineAdapter.Context.LiquidTypes.ToListAsync()).OrderBy(x => x.PreferredIndex).ToObservableCollection();
ActiveMachineAdapter.MidTankTypes = (await ActiveMachineAdapter.Context.MidTankTypes.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.CartridgeTypes = (await ActiveMachineAdapter.Context.CartridgeTypes.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.IdsPackFormulas = (await ActiveMachineAdapter.Context.IdsPackFormulas.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.HardwareVersions = (await ActiveMachineAdapter.Context.HardwareVersions.ToListAsync()).OrderByDescending(x => x.Version).ToObservableCollection();
ActiveMachineAdapter.MachineVersions = (await ActiveMachineAdapter.Context.MachineVersions.ToListAsync()).ToObservableCollection();
ActiveMachineAdapter.Organizations = (await ActiveMachineAdapter.Context.Organizations.ToListAsync()).ToObservableCollection();
bool initHwConfig = true;
Configuration machineConfigBeforeClone = null;
if (!newMachine)
{
ActiveMachine = (await new MachineBuilder(ActiveMachineAdapter.Context).Set(SelectedMachine.Guid).WithOrganization().WithConfiguration().WithSpools().BuildAsync());
_machineBeforeSave = MachineDTO.FromObservable(ActiveMachine);
if (clone)
{
machineConfigBeforeClone = ActiveMachine.Configuration;
IsNewMachine = true;
ActiveMachine = ActiveMachine.Clone();
ActiveMachine.Name = machineCreationDialogVM.Name;
ActiveMachine.SerialNumber = machineCreationDialogVM.SerialNumber;
ActiveMachine.IsDeviceRegistered = false;
ActiveMachine.DeviceId = null;
ActiveMachine.DeviceName = null;
ActiveMachine.ActivationKey = null;
ActiveMachineAdapter.Context.Machines.Add(ActiveMachine);
}
}
else
{
IsNewMachine = true;
if (machineCreationDialogVM.SelectedPrototype == null)
{
ActiveMachine = new Machine();
ActiveMachine.Configuration = new Configuration();
ActiveMachine.SerialNumber = machineCreationDialogVM.SerialNumber;
ActiveMachine.Name = machineCreationDialogVM.Name;
ActiveMachineAdapter.Context.Machines.Add(ActiveMachine);
}
else
{
try
{
initHwConfig = false;
ActiveMachine = machineCreationDialogVM.SelectedPrototype.CreateMachine(machineCreationDialogVM.SerialNumber, machineCreationDialogVM.Name);
ActiveMachine.MachineVersion = ActiveMachineAdapter.MachineVersions.FirstOrDefault(x => x.Guid == ActiveMachine.MachineVersionGuid);
if (machineCreationDialogVM.SelectedHardwareVersion != null)
{
ActiveMachine.Configuration.HardwareVersion = ActiveMachineAdapter.HardwareVersions.FirstOrDefault(x => x.Guid == machineCreationDialogVM.SelectedHardwareVersion.Guid);
}
ActiveMachineAdapter.Context.Machines.Add(ActiveMachine);
HardwareConfigurationViewVM = new HardwareConfigurationViewVM(_notification);
var version = await new HardwareVersionBuilder(ActiveMachineAdapter.Context).Set(ActiveMachine.Configuration.HardwareVersionGuid).WithHardwareComponents().BuildAsync();
HardwareConfigurationViewVM.Init(ActiveMachine.Configuration);
}
catch (Exception ex)
{
_notification.ShowError($"Invalid machine prototype.\n{ex.FlattenMessage()}");
View.NavigateTo(MachineDesignerNavigationView.MachinesView);
return;
}
}
}
ActiveMachine.OrganizationChanged -= ActiveMachine_OrganizationChanged;
ActiveMachine.OrganizationChanged += ActiveMachine_OrganizationChanged;
_all_sites = await ActiveMachineAdapter.Context.Sites.ToListAsync();
var sites = ActiveMachine.Organization != null ? _all_sites.Where(x => x.OrganizationGuid == ActiveMachine.OrganizationGuid).ToList() : new List<Site>();
sites.Insert(0, new Site() { Name = "NONE", ID = -1 });
Sites = sites;
SelectedSite = Sites.SingleOrDefault(x => x.Guid == ActiveMachine.SiteGuid);
ColorCalibrationViewVM = new ColorCalibrationViewVM(_notification, ActiveMachine, _activeMachineAdapter.Context, ActiveMachineAdapter.Rmls.FirstOrDefault())
{
Rmls = ActiveMachineAdapter.Rmls,
LiquidTypesRmls = ActiveMachineAdapter.Rmls.FirstOrDefault().LiquidTypesRmls,
};
await ColorCalibrationViewVM.Invalidate();
if (initHwConfig)
{
HardwareConfigurationViewVM = new HardwareConfigurationViewVM(_notification);
HardwareConfigurationViewVM.Init(ActiveMachine.Configuration);
}
if (!IsNewMachine)
{
await MachineUpdatesViewVM.Init(ActiveMachine, ActiveMachineAdapter.Context);
TupViewVM.Init(ActiveMachine);
}
ActiveMachine.Configuration.HardwareVersionChanged += Configuration_HardwareVersionChanged;
while (ActiveMachine.ActivationKey == null) //Generate a random password and make sure no machine matches it.
{
ActiveMachine.ActivationKey = PasswordGenerator.Generate(8, PasswordGenerator.PasswordType.Alpha, PasswordGenerator.PasswordCasing.Upper);
if (await ActiveMachineAdapter.Context.Machines.Where(x => x.ActivationKey == ActiveMachine.ActivationKey).CountAsync() == 0)
{
break;
}
ActiveMachine.ActivationKey = null;
}
IsGen1Machine = !ActiveMachine.Configuration.NoneEmptyIdsPacks.Any(x => x.LiquidType.Type == LiquidTypes.LightCyan);
View.NavigateTo(MachineDesignerNavigationView.MachineDetailsView);
}
catch (Exception ex)
{
LogManager.Log(ex, $"Error loading machine details for serial number {SelectedMachine.SerialNumber}");
_notification.ShowError($"An error occurred while trying to load the selected machine details.\n{ex.Message}");
}
finally
{
IsFree = true;
InvalidateRelayCommands();
}
}
}
private async void Configuration_HardwareVersionChanged(object sender, HardwareVersion e)
{
var version = ActiveMachine.Configuration.HardwareVersion;
if (version != null)
{
using (_notification.PushTaskItem("Loading hardware version..."))
{
try
{
if (HardwareConfigurationViewVM == null)
{
HardwareConfigurationViewVM = new HardwareConfigurationViewVM(_notification);
}
version = await new HardwareVersionBuilder(ActiveMachineAdapter.Context).Set(version.Guid).WithHardwareComponents().BuildAsync();
HardwareConfigurationViewVM.Init(ActiveMachine.Configuration);
}
catch (Exception ex)
{
LogManager.Log(ex);
}
}
}
}
private async void SaveMachine()
{
foreach (var ids in ActiveMachine.Configuration.IdsPacks)
{
ids.PackIndex = ActiveMachine.Configuration.IdsPacks.IndexOf(ids);
ids.Configuration = ActiveMachine.Configuration;
ids.ConfigurationGuid = ActiveMachine.Configuration.Guid;
}
List<String> errors = new List<string>();
if (ActiveMachine.MachineVersion == null)
{
errors.Add("Machine version is required.");
}
if (ActiveMachine.Name.IsNullOrWhiteSpace())
{
errors.Add("Machine name is required.");
}
if (ActiveMachine.Organization == null)
{
errors.Add("Machine organization is required.");
}
if (ActiveMachine.SerialNumber.IsNullOrWhiteSpace())
{
errors.Add("Machine serial number is required.");
}
if (ActiveMachine.Configuration.ApplicationDisplayPanelVersion == null)
{
errors.Add("Touch Panel is required.");
}
if (ActiveMachine.Configuration.ApplicationFirmwareVersion == null)
{
errors.Add("Application firmware is required.");
}
if (ActiveMachine.Configuration.ApplicationOsVersion == null)
{
errors.Add("Application operation system is required.");
}
if (ActiveMachine.Configuration.EmbeddedFirmwareVersion == null)
{
errors.Add("Embedded firmware is required.");
}
if (ActiveMachine.Configuration.HardwareVersion == null)
{
errors.Add("Hardware version is required.");
}
foreach (var pack in ActiveMachine.Configuration.IdsPacks)
{
if (pack.LiquidType != null || pack.CartridgeType != null || pack.Dispenser != null || pack.IdsPackFormula != null || pack.MidTankType != null)
{
if (pack.CartridgeType == null)
{
errors.Add(String.Format("Cartridge type is required on IDS pack '{0}'.", pack.PackIndex));
}
if (pack.Dispenser == null)
{
errors.Add(String.Format("Dispenser is required on IDS pack '{0}'.", pack.PackIndex));
}
if (pack.LiquidType == null)
{
errors.Add(String.Format("Liquid type is required on IDS pack '{0}'.", pack.PackIndex));
}
if (pack.MidTankType == null)
{
errors.Add(String.Format("Mid Tank type is required on IDS pack '{0}'.", pack.PackIndex));
}
if (pack.IdsPackFormula == null)
{
errors.Add(String.Format("Formula type is required on IDS pack '{0}'.", pack.PackIndex));
}
pack.IsEmpty = false;
}
else
{
pack.IsEmpty = true;
}
}
foreach (var pack in ActiveMachine.Configuration.IdsPacks.Where(x => x.Dispenser != null))
{
if (ActiveMachine.Configuration.IdsPacks.Where(x => x.Dispenser == pack.Dispenser).Count() > 1)
{
errors.Add($"Dispenser '{pack.Dispenser.SerialNumber}' is installed on multiple IDS packs.");
}
if (ActiveMachineAdapter.Context.IdsPacks.Count(x => x.ConfigurationGuid != pack.ConfigurationGuid && x.DispenserGuid == pack.DispenserGuid) > 0)
{
errors.Add($"Dispenser '{pack.Dispenser.SerialNumber}' is already installed on a different machine.");
}
}
if (ActiveMachine.Spools.GroupBy(x => x.SpoolType).Any(x => x.Count() > 1))
{
errors.Add($"Same spool type is registered multiple times.");
}
if (errors.Count > 0)
{
String errorsString = "Please fix the following validation errors before trying to save." + Environment.NewLine + Environment.NewLine;
errorsString += String.Join(Environment.NewLine, errors.Distinct());
_notification.ShowError(errorsString);
return;
}
try
{
IsFree = false;
using (_notification.PushTaskItem("Saving Machine Details..."))
{
ActiveMachine.ConfigurationGuid = ActiveMachine.Configuration.Guid;
ActiveMachine.LastUpdated = DateTime.UtcNow;
ActiveMachine.SiteGuid = SelectedSite == null ? null : (SelectedSite.ID == -1 ? null : SelectedSite.Guid);
ColorCalibrationViewVM.Save();
var hwConfig = HardwareConfigurationViewVM.GetResultingHardwareConfiguration();
ActiveMachine.Configuration.SetHardwareConfiguration(hwConfig);
await ActiveMachineAdapter.Context.SaveChangesAsync();
if (IsNewMachine)
{
_actionLogManager.InsertLog(BL.Enumerations.ActionLogType.MachineCreated, _authentication.CurrentUser, ActiveMachine.Name, ActiveMachine, "New machine created using Machine Studio.");
}
else
{
var machineAfterDTO = MachineDTO.FromObservable(ActiveMachine);
_actionLogManager.InsertLog(BL.Enumerations.ActionLogType.MachineSaved, _authentication.CurrentUser, _machineBeforeSave.Name, _machineBeforeSave, machineAfterDTO, "Machine saved using Machine Studio.");
_machineBeforeSave = machineAfterDTO;
}
if (SelectedMachine != null)
{
await LoadMachines();
}
await ColorCalibrationViewVM.Invalidate();
}
}
catch (Exception ex)
{
LogManager.Log(ex, "Error saving machine details.");
_notification.ShowError("An error occurred while trying to save the machine details" + Environment.NewLine + ex.Message);
}
finally
{
IsFree = true;
InvalidateRelayCommands();
}
}
private async void AddNewMachine()
{
List<MachinePrototype> prototypes = new List<MachinePrototype>();
List<HardwareVersion> hardwareVersions = new List<HardwareVersion>();
try
{
IsFree = false;
using (_notification.PushTaskItem("Loading machine creation data..."))
{
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
prototypes = await db.MachinePrototypes.ToListAsync();
hardwareVersions = await db.HardwareVersions.ToListAsync();
}
}
}
catch (Exception ex)
{
LogManager.Log(ex, "Error loading machine creation data.");
_notification.ShowError($"Error loading machine creation data\n{ex.FlattenMessage()}");
return;
}
finally
{
IsFree = true;
}
MachineCreationDialogVM vm = new MachineCreationDialogVM();
vm.IsNewMachine = true;
vm.Prototypes = prototypes.ToList();
vm.HardwareVersions = hardwareVersions.OrderByDescending(x => x.Version).ToList();
vm.SelectedHardwareVersion = vm.HardwareVersions.FirstOrDefault();
_notification.ShowModalDialog<MachineCreationDialogVM, Views.MachineCreationDialog>(vm, (x) =>
{
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
if (db.Machines.Any(y => y.SerialNumber == vm.SerialNumber || y.Name.ToLower() == vm.Name.ToLower()))
{
_notification.ShowError("Machine serial number or name already exists.");
return;
}
}
LoadSelectedMachine(true, false, vm);
}, () => { });
}
private async void RemoveSelectedMachine()
{
if (SelectedMachine == null) return;
if (_notification.ShowQuestion("Are you sure you want to delete the selected machine?"))
{
using (_notification.PushTaskItem("Removing machine..."))
{
try
{
IsFree = false;
var selectedMachine = SelectedMachine;
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
var machineToDelete = await new MachineBuilder(db).Set(SelectedMachine.Guid).WithConfiguration().BuildAsync();
await machineToDelete.DeleteCascadeAsync(db);
await machineToDelete.Configuration.DeleteCascadeAsync(db);
foreach (var dispenser in machineToDelete.Configuration.NoneEmptyIdsPacks.Select(x => x.Dispenser))
{
if (dispenser != null)
{
await dispenser.DeleteCascadeAsync(db);
}
}
_actionLogManager.InsertLog(ActionLogType.MachineDeleted, _authentication.CurrentUser, selectedMachine.Name, machineToDelete, "Machine deleted using Machine Studio.");
await LoadMachines();
}
}
catch (Exception ex)
{
LogManager.Log(ex, $"Error removing selected machine.");
_notification.ShowError($"An error occurred while trying to delete the selected machine.\n{ex.Message}");
}
finally
{
IsFree = true;
}
}
}
}
private void ResetDeviceRegistration()
{
if (_notification.ShowQuestion("Are you sure you wish to reset this machine device registration?"))
{
ActiveMachine.IsDeviceRegistered = false;
ActiveMachine.DeviceId = null;
ActiveMachine.DeviceName = null;
}
}
private async void MakePrototype()
{
String protoName = _notification.ShowTextInput("Enter prototype name", "name");
if (!protoName.IsNotNullOrWhiteSpace()) return;
using (_notification.PushTaskItem($"Saving machine prototype '{protoName}'..."))
{
try
{
IsFree = false;
using (var db = ObservablesContext.CreateDefault())
{
MachinePrototype prototype = MachinePrototype.CreateNew(ActiveMachine, protoName, protoName);
db.MachinePrototypes.Add(prototype);
await db.SaveChangesAsync();
}
}
catch (Exception ex)
{
_notification.ShowError($"Error creating machine prototype\n{ex.FlattenMessage()}");
}
finally
{
IsFree = true;
}
}
}
#endregion
private void CloneMachine()
{
MachineCreationDialogVM vm = new MachineCreationDialogVM();
vm.IsNewMachine = false;
_notification.ShowModalDialog<MachineCreationDialogVM, Views.MachineCreationDialog>(vm, (x) =>
{
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
if (db.Machines.Any(y => y.SerialNumber == vm.SerialNumber || y.Name.ToLower() == vm.Name.ToLower()))
{
_notification.ShowError("Machine serial number or name already exists.");
return;
}
}
LoadSelectedMachine(false, true, vm);
}, () => { });
}
private void AddNewSpool()
{
_activeMachineAdapter.Context.Spools.Add(new Spool()
{
Machine = ActiveMachine,
});
}
private void RemoveSpool()
{
if (SelectedSpool != null)
{
_activeMachineAdapter.Context.Spools.Remove(SelectedSpool);
ActiveMachine.Spools.Remove(SelectedSpool);
}
}
private async void OnFilterChanged()
{
await LoadMachines();
}
private async Task LoadMachines()
{
String filter = Filter.ToStringOrEmpty();
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
var machines = await db.Machines.Where(x => filter == String.Empty || x.SerialNumber.ToLower().StartsWith(filter.ToLower()) || x.Name.ToLower().Contains(filter.ToLower()))
.Include(x => x.Configuration)
.Include(x => x.MachineVersion.Name)
.Include(x => x.Organization.Name)
.Include(x => x.Configuration.HardwareVersion.Name)
.Include(x => x.Configuration.HardwareVersion.Version).Select(x => new
{
x.Guid,
x.SerialNumber,
x.Name,
Organization = x.Organization.Name,
MachineVersion = x.MachineVersion.Name,
HardwareVersionName = x.Configuration.HardwareVersion.Name,
HardwareVersionVersion = x.Configuration.HardwareVersion.Version,
x.IsDeviceRegistered,
x.IsDemo,
x.LastUpdated
}).OrderBy(x => x.SerialNumber).ToListAsync();
List<MachineModel> models = new List<MachineModel>();
foreach (var machine in machines)
{
MachineModel model = new MachineModel();
model.Guid = machine.Guid;
model.SerialNumber = machine.SerialNumber;
model.Name = machine.Name;
model.Organization = machine.Organization;
model.HardwareVersion = machine.HardwareVersionName + " v" + machine.HardwareVersionVersion;
model.MachineVersion = machine.MachineVersion;
model.IsDeviceRegistered = machine.IsDeviceRegistered;
model.IsDemo = machine.IsDemo;
model.LastUpdated = machine.LastUpdated;
models.Add(model);
}
Machines = models;
}
}
private void ActiveMachine_OrganizationChanged(object sender, Organization e)
{
var sites = ActiveMachine.Organization != null ? _all_sites.Where(x => x.OrganizationGuid == ActiveMachine.OrganizationGuid).ToList() : new List<Site>();
sites.Insert(0, new Site() { Name = "NONE", ID = -1 });
Sites = sites;
SelectedSite = Sites.SingleOrDefault(x => x.Guid == ActiveMachine.SiteGuid);
}
private async void UpgradeToGEN2()
{
if (!_notification.ShowQuestion("Are you sure you want to upgrade this machine configuration to GEN 2 standards?")) return;
using (_notification.PushTaskItem("Upgrading this machine to GEN 2..."))
{
try
{
IsFree = false;
var configuration = ActiveMachine.Configuration;
InvalidOperationException noneGen1Exception = new InvalidOperationException("This machine configuration does not fit within the GEN 1 standard and cannot be upgraded.");
var orderedPacks = configuration.IdsPacks.OrderBy(x => x.PackIndex).ToList();
try
{
if (!ValidateIdsPack(orderedPacks[0], LiquidTypes.Black, MidTankTypes.StandardMidTank, DispenserTypes.StandardDispenser, IdsPackFormulas.StandardColor)) throw noneGen1Exception;
if (!ValidateIdsPack(orderedPacks[1], LiquidTypes.Cyan, MidTankTypes.StandardMidTank, DispenserTypes.StandardDispenser, IdsPackFormulas.StandardColor)) throw noneGen1Exception;
if (!ValidateIdsPack(orderedPacks[2], LiquidTypes.Magenta, MidTankTypes.StandardMidTank, DispenserTypes.StandardDispenser, IdsPackFormulas.StandardColor)) throw noneGen1Exception;
if (!ValidateIdsPack(orderedPacks[3], LiquidTypes.Yellow, MidTankTypes.StandardMidTank, DispenserTypes.StandardDispenser, IdsPackFormulas.StandardColor)) throw noneGen1Exception;
if (!ValidateIdsPack(orderedPacks[4], LiquidTypes.TransparentInk, MidTankTypes.StandardMidTank, DispenserTypes.StandardDispenser, IdsPackFormulas.TransparentLiquid)) throw noneGen1Exception;
if (!orderedPacks[5].IsEmpty) throw noneGen1Exception;
if (!ValidateIdsPack(orderedPacks[6], LiquidTypes.Cleaner, MidTankTypes.StandardMidTank, DispenserTypes.StandardDispenser, IdsPackFormulas.CleanerLiquid)) throw noneGen1Exception;
if (!ValidateIdsPack(orderedPacks[7], LiquidTypes.Lubricant, MidTankTypes.StandardMidTank, DispenserTypes.StandardDispenser, IdsPackFormulas.Lubricant)) throw noneGen1Exception;
}
catch
{
throw noneGen1Exception;
}
var cleanerPack = orderedPacks[6];
var lubricantPack = orderedPacks[7];
var emptyPack = orderedPacks[5];
cleanerPack.MidTankType = ActiveMachineAdapter.MidTankTypes.First(x => x.Type == MidTankTypes.NoMidTank);
cleanerPack.IdsPackFormula = ActiveMachineAdapter.IdsPackFormulas.First(x => x.Type == IdsPackFormulas.LightInksCleanerLiquid);
cleanerPack.Dispenser.DispenserType = ActiveMachineAdapter.DispenserTypes.First(x => x.Type == DispenserTypes.CleanerDispenser);
cleanerPack.PackIndex = 8;
lubricantPack.MidTankType = ActiveMachineAdapter.MidTankTypes.First(x => x.Type == MidTankTypes.LubricantMidTank);
lubricantPack.IdsPackFormula = ActiveMachineAdapter.IdsPackFormulas.First(x => x.Type == IdsPackFormulas.LightInksLubricantLiquid);
lubricantPack.Dispenser.DispenserType = ActiveMachineAdapter.DispenserTypes.First(x => x.Type == DispenserTypes.LubricantDispenser);
lubricantPack.PackIndex = 9;
var lightCyanDispenser = await ActiveMachineAdapter.Context.Dispensers.Include(x => x.IdsPacks).FirstOrDefaultAsync(x => x.SerialNumber.StartsWith(ActiveMachine.SerialNumber) && x.IdsPacks.Count == 0);
int newDispenserStartIndex = 9;
if (lightCyanDispenser == null)
{
lightCyanDispenser = new Dispenser();
lightCyanDispenser.NlPerPulse = orderedPacks[1].Dispenser.NlPerPulse;
lightCyanDispenser.SerialNumber = $"{ActiveMachine.SerialNumber}-{newDispenserStartIndex++}";
lightCyanDispenser.DispenserType = ActiveMachineAdapter.DispenserTypes.First(x => x.Type == DispenserTypes.StandardDispenser);
}
IdsPack lightCyanPack = new IdsPack();
lightCyanPack.PackIndex = 5;
lightCyanPack.LiquidType = ActiveMachineAdapter.LiquidTypes.First(x => x.Type == LiquidTypes.LightCyan);
lightCyanPack.MidTankType = ActiveMachineAdapter.MidTankTypes.First(x => x.Type == MidTankTypes.StandardMidTank);
lightCyanPack.IdsPackFormula = ActiveMachineAdapter.IdsPackFormulas.First(x => x.Type == IdsPackFormulas.LightColor);
lightCyanPack.CartridgeType = ActiveMachineAdapter.CartridgeTypes.First(x => x.Type == CartridgeTypes.StandardCartridge);
lightCyanPack.Dispenser = lightCyanDispenser;
configuration.IdsPacks.Add(lightCyanPack);
IdsPack lightMagentaPack = new IdsPack();
lightMagentaPack.PackIndex = 6;
lightMagentaPack.LiquidType = ActiveMachineAdapter.LiquidTypes.First(x => x.Type == LiquidTypes.LightMagenta);
lightMagentaPack.MidTankType = ActiveMachineAdapter.MidTankTypes.First(x => x.Type == MidTankTypes.StandardMidTank);
lightMagentaPack.IdsPackFormula = ActiveMachineAdapter.IdsPackFormulas.First(x => x.Type == IdsPackFormulas.LightColor);
lightMagentaPack.CartridgeType = ActiveMachineAdapter.CartridgeTypes.First(x => x.Type == CartridgeTypes.StandardCartridge);
lightMagentaPack.Dispenser = new Dispenser()
{
NlPerPulse = orderedPacks[2].Dispenser.NlPerPulse,
SerialNumber = $"{ActiveMachine.SerialNumber}-{newDispenserStartIndex++}",
DispenserType = ActiveMachineAdapter.DispenserTypes.First(x => x.Type == DispenserTypes.StandardDispenser)
};
configuration.IdsPacks.Add(lightMagentaPack);
IdsPack lightYellowPack = new IdsPack();
lightYellowPack.PackIndex = 7;
lightYellowPack.LiquidType = ActiveMachineAdapter.LiquidTypes.First(x => x.Type == LiquidTypes.LightYellow);
lightYellowPack.MidTankType = ActiveMachineAdapter.MidTankTypes.First(x => x.Type == MidTankTypes.StandardMidTank);
lightYellowPack.IdsPackFormula = ActiveMachineAdapter.IdsPackFormulas.First(x => x.Type == IdsPackFormulas.LightColor);
lightYellowPack.CartridgeType = ActiveMachineAdapter.CartridgeTypes.First(x => x.Type == CartridgeTypes.StandardCartridge);
lightYellowPack.Dispenser = new Dispenser()
{
NlPerPulse = orderedPacks[3].Dispenser.NlPerPulse,
SerialNumber = $"{ActiveMachine.SerialNumber}-{newDispenserStartIndex++}",
DispenserType = ActiveMachineAdapter.DispenserTypes.First(x => x.Type == DispenserTypes.StandardDispenser)
};
configuration.IdsPacks.Add(lightYellowPack);
configuration.IdsPacks.Remove(emptyPack);
ActiveMachineAdapter.Context.IdsPacks.Remove(emptyPack);
var packs = configuration.IdsPacks.ToList();
configuration.IdsPacks.Clear();
foreach (var pack in packs.OrderBy(x => x.PackIndex))
{
configuration.IdsPacks.Add(pack);
}
ActiveMachine.LightInksInstalled = true;
ActiveMachine.BtsrInstalled = true;
IsGen1Machine = false;
_notification.ShowInfo("Machine configuration successfully upgraded to GEN 2.");
}
catch (Exception ex)
{
LogManager.Log(ex, "Error upgrading machine to GEN 2.");
_notification.ShowError($"Error upgrading this machine to GEN 2.\n{ex.FlattenMessage()}");
}
finally
{
IsFree = true;
}
}
}
private bool ValidateIdsPack(IdsPack pack, LiquidTypes liquidType, MidTankTypes midTankType, DispenserTypes dispenserType, IdsPackFormulas formula)
{
if (pack.LiquidType.Type != liquidType) return false;
if (pack.MidTankType.Type != midTankType) return false;
if (pack.Dispenser.DispenserType.Type != dispenserType) return false;
if (pack.IdsPackFormula.Type != formula) return false;
return true;
}
}
}