aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioModuleAttribute.cs
blob: b9212a9e3df6d01de663a32ebb7c8807d7d1fa17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tango.MachineStudio.Common
{
    [AttributeUsage(AttributeTargets.Class)]
    public class StudioModuleAttribute : Attribute
    {
        public int Index { get; set; }

        public StudioModuleAttribute(int index)
        {
            Index = index;
        }
    }
}
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;

namespace Tango.MachineStudio.MachineDesigner.ViewModels
{
    public class MainViewVM : StudioViewModel<IMainView>
    {
        private INotificationProvider _notification;
        private ActionTimer _machines_action_timer;
        private ActionTimer _dispensers_action_timer;

        #region Properties

        private ObservablesStaticCollections _machinesAdapter;
        public ObservablesStaticCollections MachinesAdapter
        {
            get { return _machinesAdapter; }
            set { _machinesAdapter = value; RaisePropertyChangedAuto(); }
        }

        private ObservablesStaticCollections _activeMachineAdapter;
        public ObservablesStaticCollections ActiveMachineAdapter
        {
            get { return _activeMachineAdapter; }
            set { _activeMachineAdapter = value; RaisePropertyChangedAuto(); }
        }

        private Machine _selectedMachine;
        /// <summary>
        /// Gets or sets the selected machine from the drop down.
        /// </summary>
        public Machine 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 ColorLab.ViewModels.MainViewVM _colorLabVM;
        public ColorLab.ViewModels.MainViewVM ColorLabVM
        {
            get { return _colorLabVM; }
            set { _colorLabVM = 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; }
        #endregion

        #region Constructors

        public MainViewVM()
        {

        }

        /// <summary>
        /// Initializes a new instance of the <see cref="MainViewVM"/> class.
        /// </summary>
        public MainViewVM(INotificationProvider notification)
        {
            MachinesAdapter = new ObservablesStaticCollections(ObservablesContext.CreateDefault());
            _notification = notification;

            _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 < 8);
            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);
        }
        #endregion

        #region Application Ready

        public override async void OnApplicationReady()
        {
            MachinesAdapter.MachineVersions = (await MachinesAdapter.Context.MachineVersions.ToListAsync()).ToObservableCollection();
            ColorLabVM = new ColorLab.ViewModels.MainViewVM(_notification) { IsHosted = true };
        }

        #endregion

        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())).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);
        }

        /// <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;
        }

        /// <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;
        }

        /// <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, MachineVersion selectedVersion = null)
        {
            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()).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()).ToObservableCollection();
                    ActiveMachineAdapter.MachineVersions = (await ActiveMachineAdapter.Context.MachineVersions.ToListAsync()).ToObservableCollection();
                    ActiveMachineAdapter.Organizations = (await ActiveMachineAdapter.Context.Organizations.ToListAsync()).ToObservableCollection();

                    if (!newMachine)
                    {
                        ActiveMachine = (await new MachineBuilder(ActiveMachineAdapter.Context).Set(SelectedMachine.Guid).WithOrganization().WithConfiguration().WithSpools().BuildAsync());

                        if (clone)
                        {
                            ActiveMachine = ActiveMachine.Clone();
                            ActiveMachine.Name = "";
                            ActiveMachine.SerialNumber = "";
                            ActiveMachineAdapter.Context.Machines.Add(ActiveMachine);
                        }
                    }
                    else
                    {
                        if (selectedVersion == null)
                        {
                            ActiveMachine = new Machine();
                            ActiveMachine.Configuration = new Configuration();
                            ActiveMachineAdapter.Context.Machines.Add(ActiveMachine);
                        }
                        else
                        {
                            ActiveMachine = selectedVersion.CreatePrototypeMachine(ActiveMachineAdapter.Context);
                            ActiveMachineAdapter.Context.Machines.Add(ActiveMachine);
                        }
                    }

                    ColorLabVM.InitHost(ActiveMachineAdapter.Context, ActiveMachine, ActiveMachineAdapter.Rmls, ActiveMachineAdapter.Rmls.FirstOrDefault());

                    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 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.ProductionDate = DateTime.UtcNow;
                    await ActiveMachineAdapter.Context.SaveChangesAsync();

                    await ColorLabVM.SaveChanges();

                    if (SelectedMachine != null)
                    {
                        await SelectedMachine.Reload(MachinesAdapter.Context);
                    }
                }
            }
            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 void AddNewMachine()
        {
            MachineCreationDialogVM vm = new MachineCreationDialogVM();
            vm.MachineVersions = MachinesAdapter.MachineVersions.ToList();
            _notification.ShowModalDialog<MachineCreationDialogVM, Views.MachineCreationDialog>(vm, (x) =>
            {
                if (vm.SelectedMachineVersion != null && String.IsNullOrWhiteSpace(vm.SelectedMachineVersion.PrototypeMachineData))
                {
                    _notification.ShowError("The selected version does not contain any prototype machine data.");
                    return;
                }

                LoadSelectedMachine(true, false, vm.SelectedMachineVersion);
            }, () => { });
        }

        private async void RemoveSelectedMachine()
        {
            if (_notification.ShowQuestion("Are you sure you want to delete the selected machine?"))
            {
                using (_notification.PushTaskItem("Removing machine..."))
                {
                    try
                    {
                        IsFree = false;
                        await SelectedMachine.DeleteCascadeAsync(MachinesAdapter.Context);
                        MachinesAdapter.Context.Machines.Remove(SelectedMachine);
                    }
                    catch (Exception ex)
                    {
                        LogManager.Log(ex, $"Error removing machine {SelectedMachine.SerialNumber}.");
                        _notification.ShowError($"An error occurred while trying to delete the selected machine.\n{ex.Message}");
                    }
                    finally
                    {
                        IsFree = true;
                    }
                }
            }
        }

        #endregion

        private void CloneMachine()
        {
            LoadSelectedMachine(false, true);
        }

        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 void OnFilterChanged()
        {
            if (Filter != null)
            {
                _machines_action_timer.ResetReplace(() =>
                {
                    Task.Factory.StartNew(() =>
                    {
                        IsFree = false;
                        MachinesAdapter.Machines = MachinesAdapter.Context.Machines.Where(x => x.SerialNumber.StartsWith(Filter)).Include(x => x.Organization).Include(x => x.MachineVersion).ToSynchronizedObservableCollection();
                        IsFree = true;
                    });
                });
            }
        }
    }
}