aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.Web/Storage/ExtensionMethods.cs
blob: e9e361f21541d127496bd016588ebaef21a2c8f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
using Microsoft.WindowsAzure.Storage.Blob;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tango.Web.Storage
{
    public static class ExtensionMethods
    {
        public static CloudBlockBlob CreateEmptyBlob(this CloudBlobContainer container, String name)
        {
            CloudBlockBlob emptyBlob = container.GetBlockBlobReference(name);
            using (MemoryStream ms = new MemoryStream())
            {
                emptyBlob.UploadFromStream(ms);//Empty memory stream. Will create an empty blob.
            }

            return emptyBlob;
        }

        public static CloudBlockBlob UploadNewBlob(this CloudBlobContainer container, Stream stream, String name)
        {
            CloudBlockBlob emptyBlob = container.GetBlockBlobReference(name);
            emptyBlob.UploadFromStream(stream);
            return emptyBlob;
        }

        public static String GenerateReadSignature(this CloudBlockBlob blob, TimeSpan duration)
        {
            String signature = blob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
            {
                SharedAccessStartTime = DateTime.UtcNow,
                SharedAccessExpiryTime = DateTime.UtcNow.Add(duration),
                Permissions = SharedAccessBlobPermissions.Read
            });

            return new Uri(blob.Uri + signature).ToString();
        }

        public static String GenerateWriteSignature(this CloudBlockBlob blob, TimeSpan duration)
        {
            String signature = blob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
            {
                SharedAccessStartTime = DateTime.UtcNow,
                SharedAccessExpiryTime = DateTime.UtcNow.Add(duration),
                Permissions = SharedAccessBlobPermissions.Write
            });

            return new Uri(blob.Uri + signature).ToString();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.BL;
using Tango.BL.Entities;
using Tango.Integration.Operation;
using Tango.Settings;
using Tango.PPC.Common.Application;
using Tango.Core.DI;
using Tango.PPC.Common;
using System.Windows;
using Tango.Core;
using System.IO;
using Tango.Core.Helpers;
using Tango.PPC.Common.Modules;
using System.Windows.Threading;
using Tango.Transport.Adapters;
using Tango.PMR.Connection;
using Tango.PPC.Common.Connection;
using Tango.SQLExaminer;
using System.Data.SqlClient;
using Tango.BL.Builders;
using Tango.PPC.Common.Threading;
using System.Diagnostics;
using Tango.PPC.Common.EventLogging;
using Tango.BL.Enumerations;
using Tango.PPC.Common.Notifications;
using Tango.PPC.Common.WatchDog;
using Tango.PPC.UI.Dialogs;
using Tango.Core.Threading;
using Tango.PPC.Common.Messages;
using Tango.Core.ExtensionMethods;
using Tango.PPC.Common.Navigation;
using Tango.PPC.Common.Synchronization;

namespace Tango.PPC.UI.PPCApplication
{
    /// <summary>
    /// Represents the default PPC application manager.
    /// </summary>
    /// <seealso cref="Tango.Core.ExtendedObject" />
    /// <seealso cref="Tango.PPC.Common.Application.IPPCApplicationManager" />
    public class DefaultPPCApplicationManager : ExtendedObject, IPPCApplicationManager
    {
        private List<PPCViewModel> _notifiedViewModels;
        private IMachineProvider _machineProvider;
        private Machine _machine;
        private IDispatcherProvider _dispatcher;
        private IEventLogger _eventLogger;
        private IPPCModuleLoader _moduleLoader;
        private INotificationProvider _notificationProvider;
        private IMachineDataSynchronizer _machineDataSynchronizer;
        private WatchDogServer _watchdogServer;
        private ObservablesContext _machineContext;
        private ActionTimer _screenLockTimer;

        /// <summary>
        /// Occurs when a system restart is required.
        /// </summary>
        public event EventHandler SystemRestartRequired;

        /// <summary>
        /// Occurs when the application has started.
        /// </summary>
        public event EventHandler ApplicationStarted;

        /// <summary>
        /// Occurs when all PPC modules are ready and initialized.
        /// </summary>
        public event EventHandler ModulesInitialized;

        /// <summary>
        /// Occurs when the application is ready and all modules are views are loaded.
        /// </summary>
        public event EventHandler ApplicationReady;

        /// <summary>
        /// Occurs when machine setup is required.
        /// </summary>
        public event EventHandler SetupRequired;

        /// <summary>
        /// Occurs when the main window content has been rendered.
        /// </summary>
        public event EventHandler ContentRendered;

        /// <summary>
        /// Occurs when the application has encountered an error when initializing.
        /// </summary>
        public event EventHandler<Exception> ApplicationInitializationError;

        /// <summary>
        /// Gets a value indicating whether the application is shutting down.
        /// </summary>
        public bool IsShuttingDown { get; private set; }

        private bool _isInTechnicianMode;
        /// <summary>
        /// Gets a value indicating whether the application is in technician mode.
        /// </summary>
        public bool IsInTechnicianMode
        {
            get { return _isInTechnicianMode; }
            set { _isInTechnicianMode = value; RaisePropertyChangedAuto(); }
        }

        /// <summary>
        /// Gets the application version.
        /// </summary>
        public Version Version
        {
            get
            {
                return AssemblyHelper.GetCurrentAssemblyVersion();
            }
        }

        /// <summary>
        /// Gets the application build date.
        /// </summary>
        public String BuildDate
        {
            get
            {
                return AssemblyHelper.GetCurrentAssemblyBuildDate().ToShortDateString();
            }
        }

        /// <summary>
        /// Gets the application startup date.
        /// </summary>
        public DateTime StartUpDate { get; private set; }

        /// <summary>
        /// Gets a value indicating whether an update has occurred before the application started.
        /// </summary>
        public bool IsAfterUpdate { get; private set; }

        private bool _isScreenLocked;
        /// <summary>
        /// Gets or sets a value indicating whether the screen is currently locked.
        /// </summary>
        public bool IsScreenLocked
        {
            get { return _isScreenLocked; }
            set { _isScreenLocked = value; RaisePropertyChangedAuto(); }
        }

        /// <summary>
        /// Gets the firmware version.
        /// </summary>
        public Version FirmwareVersion
        {
            get
            {
                return Version.Parse(SettingsManager.Default.GetOrCreate<PPCSettings>().FirmwareVersion);
            }
        }

        /// <summary>
        /// Gets or sets the application folder.
        /// </summary>
        public String StartPath { get; private set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="DefaultPPCApplicationManager"/> class.
        /// </summary>
        public DefaultPPCApplicationManager(IMachineProvider machineProvider, IDispatcherProvider dispatcherProvider, IEventLogger eventLogger, IPPCModuleLoader moduleLoader, INotificationProvider notificationProvider, IMachineDataSynchronizer machineDataSynchronizer)
        {
            StartPath = AssemblyHelper.GetCurrentAssemblyFolder();

            _notificationProvider = notificationProvider;
            _machineProvider = machineProvider;
            _dispatcher = dispatcherProvider;
            _eventLogger = eventLogger;
            _moduleLoader = moduleLoader;
            _machineDataSynchronizer = machineDataSynchronizer;

            if (!DesignMode)
            {
                _notifiedViewModels = new List<PPCViewModel>();

                MainWindow.Instance.ContentRendered += (_, __) =>
                {
                    OnMainWindowContentRendered();
                };
            }
        }

        /// <summary>
        /// Called when the main window content has been rendered
        /// </summary>
        private void OnMainWindowContentRendered()
        {
            LogManager.Log("Main window content rendered.");

            ContentRendered?.Invoke(this, new EventArgs());

            StartApplication();
        }

        private async void StartApplication()
        {
            PPCSettings settings = null;

            bool initialized = false;
            bool isAfterSetup = false;

            StartUpDate = DateTime.Now;

            await Task.Factory.StartNew(() =>
            {
                try
                {
                    LogManager.Log("Reading PPC settings...");
                    settings = SettingsManager.Default.GetOrCreate<PPCSettings>();

                    LogManager.Log(settings.ToJsonString());

                    //Start watchdog
                    _watchdogServer = new WatchDogServer(Application.Current.Dispatcher);
#if !DEBUG

                    if (settings.EnableWatchDog)
                    {
                        _watchdogServer.Start();
                    }
#endif

                    LogManager.Log("Reading Core settings...");
                    var coreSettings = SettingsManager.Default.GetOrCreate<CoreSettings>();

                    if (!SettingsManager.Default.IsFileExists())
                    {
                        LogManager.Log("Settings file does not exists. creating...");
                        settings.Save();
                    }

                    if (App.StartupArgs.Contains("-update_ok"))
                    {
                        LogManager.Log("Application started with '-update_ok' startup arguments. The application has been successfully updated.");

                        if (settings.ApplicationState == ApplicationStates.PreSetup || settings.ApplicationState == ApplicationStates.FactoryRestore)
                        {
                            isAfterSetup = true;
                            LogManager.Log("System restart is required.");
                        }
                        else
                        {
                            IsAfterUpdate = true;
                        }

                        settings.ApplicationState = ApplicationStates.Ready;
                        settings.Save();

                        if (isAfterSetup)
                        {
                            SystemRestartRequired?.Invoke(this, new EventArgs());
                            return;
                        }
                    }

                    if (settings.ApplicationState == ApplicationStates.Ready)
                    {
                        LogManager.Log("Initializing ObservablesStaticCollections...");
                        ObservablesStaticCollections.Instance.Initialize();
                        LogManager.Log("Loading machine from database...");
                        _machineContext = ObservablesContext.CreateDefault();
                        _machine = new MachineBuilder(_machineContext).SetFirst().WithVersion().WithSettings().WithOrganization().WithConfiguration().WithSpools().WithCats().Build();


                    }

                    initialized = true;
                }
                catch (Exception ex)
                {
                    LogManager.Log(ex, "Application Initialization Error!");
                    ApplicationInitializationError?.Invoke(this, ex);
                    return;
                }
            });


            if (initialized)
            {
                try
                {
                    if (settings.ApplicationState == ApplicationStates.PreSetup || settings.ApplicationState == ApplicationStates.FactoryRestore)
                    {
                        LogManager.Log($"The application is in {settings.ApplicationState} state. database initialization skipped. Invoking setup required event!");
                        SetupRequired?.Invoke(this, new EventArgs());
                    }
                    else
                    {
                        PostDbInitialize();
                    }
                }
                catch (Exception ex)
                {
                    LogManager.Log(ex, "Application Post Initialization Error!");
                    ApplicationInitializationError?.Invoke(this, ex);
                    return;
                }
            }
        }

        /// <summary>
        /// Called when the database has been initialized
        /// </summary>
        private void PostDbInitialize()
        {
            LogManager.Log($"Raising {nameof(ApplicationStarted)} event...");

            _eventLogger.Log(EventTypes.APPLICATION_STARTED, "Application Started!");
            ApplicationStarted?.Invoke(this, new EventArgs());

            LogManager.Log("Invoking PPC view models OnApplicationStarted methods...");
            foreach (var vm in TangoIOC.Default.GetAllInstancesByBase<PPCViewModel>())
            {
                if (!_notifiedViewModels.Contains(vm))
                {
                    LogManager.Log($"Invoking {vm.GetType().Name}.OnApplicationStarted...");
                    vm.OnApplicationStarted();
                    _notifiedViewModels.Add(vm);
                }
            }

            var internalModules = this.GetType().Assembly.GetTypes().Where(xx => typeof(PPCModuleBase).IsAssignableFrom(xx)).ToList();

            LogManager.Log("Waiting for IPPCModuleLoader instance injection...");
            TangoIOC.Default.GetInstanceWhenAvailable<IPPCModuleLoader>((loader) =>
            {
                LogManager.Log("Module loader instance has been registered. Registering for the ModulesLoaded event...");

                loader.ModulesLoaded += (x, y) =>
                {
                    LogManager.Log("Loading modules views");
                    _dispatcher.InvokeBlock(() =>
                    {
                        foreach (var module in TangoIOC.Default.GetInstance<IPPCModuleLoader>().UserModules)
                        {
                            if (!Views.LayoutView.Instance.NavigationControl.Elements.ToList().Exists(m => m.GetType() == module.MainViewType))
                            {
                                try
                                {
                                    LogManager.Log("Loading module view " + module.Name + "...");
                                    FrameworkElement view = Activator.CreateInstance(module.MainViewType) as FrameworkElement;
                                    SharedUI.Controls.NavigationControl.SetNavigationName(view, module.Name);
                                    Views.LayoutView.Instance.NavigationControl.Elements.Add(view);
                                }
                                catch (Exception ex)
                                {
                                    LogManager.Log(ex, $"Error loading module view for module {module.Name}.");
                                }
                            }
                        }

                        //Adding internal modules.
                        LogManager.Log("Loading internal modules...");
                        foreach (var type in internalModules)
                        {
                            var module = Activator.CreateInstance(type) as IPPCModule;
                            LogManager.Log("Loading module view " + module.Name + "...");
                            FrameworkElement view = Activator.CreateInstance(module.MainViewType) as FrameworkElement;
                            SharedUI.Controls.NavigationControl.SetNavigationName(view, module.Name);
                            Views.LayoutView.Instance.NavigationControl.Elements.Add(view);
                            _moduleLoader.AllModules.Add(module);
                            _moduleLoader.UserModules.Add(module);
                        }
                    });

                    LogManager.Log($"{loader.UserModules.Count} modules loaded.");

                    LogManager.Log($"Invoking {nameof(ModulesInitialized)} event.");
                    ModulesInitialized?.Invoke(this, new EventArgs());

                    FinalizeModuleInitialization();
                };
            });
        }

        /// <summary>
        /// Finalizes the module initialization.
        /// </summary>
        private void FinalizeModuleInitialization()
        {
            var settings = SettingsManager.Default.GetOrCreate<PPCSettings>();

            LogManager.Log("Finalizing application initialization...");

            LogManager.Log("Initializing Machine Provider...");
            _machineProvider.Init(_machine, _machineContext);

            LogManager.Log("Starting Machine Data Synchronizer...");
            _machineDataSynchronizer.IsEnabled = true;

            LogManager.Log("Applications initialization completed!");

            LogManager.Log("Checking for un-notified PPC view models...");
            foreach (var vm in TangoIOC.Default.GetAllInstancesByBase<PPCViewModel>())
            {
                if (!_notifiedViewModels.Contains(vm))
                {
                    LogManager.Log($"Invoking {vm.GetType().Name}.OnApplicationStarted...");
                    vm.OnApplicationStarted();
                    _notifiedViewModels.Add(vm);
                }
            }

            _dispatcher.Invoke(() =>
            {
                LogManager.Log($"Invoking {nameof(ApplicationReady)} event.");
                ApplicationReady?.Invoke(this, new EventArgs());

                LogManager.Log("Notifying view models about application ready...");
                foreach (var vm in TangoIOC.Default.GetAllInstancesByBase<PPCViewModel>())
                {
                    LogManager.Log($"Invoking {vm.GetType().Name}.OnApplicationReady...");
                    vm.OnApplicationReady();
                }

                if (settings.EnableTechnicianModeByDefault)
                {
                    EnterTechnicianMode(false);
                }

                if (settings.EnableLockScreen)
                {
                    _screenLockTimer = new ActionTimer(settings.LockScreenTimeout);
                    _screenLockTimer.ResetReplace(ScreenLockTimerAction);
                }

                TangoMessenger.Default.Register<MachineSettingsSavedMessage>((msg) =>
                {
                    if (_screenLockTimer != null)
                    {
                        _screenLockTimer.Dispose();
                        _screenLockTimer = null;
                    }

                    if (settings.EnableLockScreen)
                    {
                        _screenLockTimer = new ActionTimer(settings.LockScreenTimeout);
                        _screenLockTimer.ResetReplace(ScreenLockTimerAction);
                    }
                });
            });
        }

        /// <summary>
        /// Shutdown the application.
        /// </summary>
        public void ShutDown()
        {
            if (IsShuttingDown) return;

            IsShuttingDown = true;

            try
            {
                LogManager.Log("Shutting down application...");
                _watchdogServer.Dispose();

                foreach (var vm in TangoIOC.Default.GetAllInstancesByBase<PPCViewModel>())
                {
                    vm.OnApplicationShuttingDown();
                }
            }
            catch { }

            Environment.Exit(0);
        }

        /// <summary>
        /// Restarts the application.
        /// </summary>
        public async void Restart()
        {
            if (IsShuttingDown) return;

            IsShuttingDown = true;

            try
            {
                _dispatcher.Invoke(() =>
                {
                    var nav = TangoIOC.Default.GetInstance<INavigationManager>();
                    if (nav != null)
                    {
                        nav.NavigateTo(NavigationView.RestartingView);
                    }
                });

                LogManager.Log("Restarting the application...");

                await Task.Delay(8000);

                _watchdogServer.Dispose();

                foreach (var vm in TangoIOC.Default.GetAllInstancesByBase<PPCViewModel>())
                {
                    vm.OnApplicationShuttingDown();
                }
            }
            catch { }

            try
            {
                if (_machineProvider.MachineOperator.State == Transport.TransportComponentState.Connected)
                {
                    _machineProvider.MachineOperator.Adapter.Disconnect().Wait();
                }
            }
            catch { }

            Process.Start(Application.ResourceAssembly.Location);
            Environment.Exit(0);
        }

        /// <summary>
        /// Runs the updater utility and exits the application.
        /// </summary>
        public void UpdateApplication(String updaterPath, String arguments)
        {
            if (IsShuttingDown) return;

            IsShuttingDown = true;

            try
            {
                _watchdogServer.Dispose();

                foreach (var vm in TangoIOC.Default.GetAllInstancesByBase<PPCViewModel>())
                {
                    vm.OnApplicationShuttingDown();
                }
            }
            catch { }

            try
            {
                SettingsManager.Default.GetOrCreate<PPCSettings>().PreviousApplicationVersion = Version.ToString();
                SettingsManager.Default.Save();
            }
            catch { }

            LogManager.Log($"Executing '{updaterPath}' with arguments '{arguments}'...");
            Process.Start(updaterPath, arguments);

            LogManager.Log("Terminating application...");
            Environment.Exit(0);
        }

        /// <summary>
        /// Enteres the application technician mode.
        /// </summary>
        public async void EnterTechnicianMode(bool displayNotification = true)
        {
            if (displayNotification)
            {
                var vm = await _notificationProvider.ShowDialog<TechnicianModeLoginViewVM>();

                if (vm.DialogResult)
                {
                    if (vm.Password == "Aa123456")
                    {
                        IsInTechnicianMode = true;
                        _moduleLoader.AllModules.ToList().ForEach(x => x.OnTechnicianEntered());
                        await _notificationProvider.ShowInfo("Technician mode is now enabled.");
                    }
                    else
                    {
                        await _notificationProvider.ShowError("Invalid technician mode password.");
                        EnterTechnicianMode();
                    }
                }
            }
            else
            {
                IsInTechnicianMode = true;
                _moduleLoader.AllModules.ToList().ForEach(x => x.OnTechnicianEntered());
            }
        }

        /// <summary>
        /// Exits the application technician mode.
        /// </summary>
        public void ExitTechnicianMode()
        {
            IsInTechnicianMode = false;
            _moduleLoader.AllModules.ToList().ForEach(x => x.OnTechnicianExited());
            _notificationProvider.ShowInfo("Technician mode is now disabled.");
        }

        /// <summary>
        /// Invokes a dialog for entering a password and releasing the screen lock.
        /// </summary>
        public async void ReleaseScreenLock()
        {
            if (IsScreenLocked)
            {
                var vm = await _notificationProvider.ShowDialog<ScreenLockViewVM>();

                if (vm.DialogResult)
                {
                    if (vm.Password == SettingsManager.Default.GetOrCreate<PPCSettings>().LockScreenPassword)
                    {
                        IsScreenLocked = false;
                        ResetScreenLockTimer();
                    }
                }
            }
        }

        public void ResetScreenLockTimer()
        {
            if (_screenLockTimer != null)
            {
                _screenLockTimer.ResetReplace(ScreenLockTimerAction);
            }
        }

        private void ScreenLockTimerAction()
        {
            IsScreenLocked = true;
        }
    }
}