aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/EmergencyViewVM.cs
blob: 87b3c012b1d0a8ceb3ebd90a4ac497da5ab90b8c (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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.Integration.Emergency;
using Tango.PPC.Common;
using Tango.PPC.Common.Navigation;

namespace Tango.PPC.UI.ViewModels
{
    public class EmergencyViewVM : PPCViewModel
    {
        private bool _isActive;

        public override void OnApplicationStarted()
        {

        }

        public override void OnApplicationReady()
        {
            base.OnApplicationReady();
            MachineProvider.MachineOperator.EmergencyNotificationProvider.StatusChanged += EmergencyNotificationProvider_StatusChanged;
        }

        private void EmergencyNotificationProvider_StatusChanged(object sender, EmergencyStatusChangedEventArgs e)
        {
            InvokeUI(async () =>
            {
                if (e.Status == EmergencyStatus.On && !_isActive)
                {
                    LogManager.Log("Emergency switch activated...");
                    _isActive = true;
                    await NavigationManager.NavigateTo(NavigationView.EmergencyView);
                }
                else if (_isActive)
                {
                    LogManager.Log("Emergency switch deactivated...");
                    _isActive = false;
                    await NavigationManager.NavigateTo(NavigationView.LayoutView);
                }

                if (e.Status == EmergencyStatus.Error && e.ErrorException != null)
                {
                    LogManager.Log(e.ErrorException, "Error occurred while detecting emergency switch.");
                }
            });
        }
    }
}
ht .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
using Google.Protobuf;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Tango.BL;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.Core;
using Tango.Integration.ExternalBridge;
using Tango.Logging;
using Tango.MachineStudio.Common.Authentication;
using Tango.MachineStudio.Common.Diagnostics;
using Tango.MachineStudio.Common.StudioApplication;
using Tango.PMR.Diagnostics;
using Tango.Integration.Operation;

namespace Tango.MachineStudio.Common.EventLogging
{
    /// <summary>
    /// Represents the default database events logger.
    /// </summary>
    /// <seealso cref="IEventLogger" />
    public class DefaultEventLogger : ExtendedObject, IEventLogger
    {
        private ObservablesContext _db;
        private Thread _logThread;
        private ConcurrentQueue<MachinesEvent> _events;
        private IStudioApplicationManager _application;
        private IAuthenticationProvider _authentication;
        private Dictionary<EventTypes, BL.Entities.EventType> _eventTypesGuids;
        private String _hostName;
        private bool _isInitialized;
        private List<MachinesEvent> _pendingEvents;

        #region Events

        /// <summary>
        /// Occurs when a new machine event has been logged.
        /// </summary>
        public event EventHandler<MachinesEvent> NewLog;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="DefaultEventLogger"/> class.
        /// </summary>
        /// <param name="applicationManager">The application manager.</param>
        /// <param name="authenticationProvider">The authentication provider.</param>
        public DefaultEventLogger(IStudioApplicationManager applicationManager, IAuthenticationProvider authenticationProvider)
        {
            _hostName = Environment.MachineName;

            _events = new ConcurrentQueue<MachinesEvent>();
            _pendingEvents = new List<MachinesEvent>();

            _eventTypesGuids = new Dictionary<EventTypes, BL.Entities.EventType>();

            _application = applicationManager;
            _authentication = authenticationProvider;
            _logThread = new Thread(LogThreadMethod);
            _logThread.IsBackground = true;
            _logThread.Start();

            _application.ConnectedMachineChanged += _application_ConnectedMachineChanged;
        }

        #endregion

        #region Private Methods

        private void Init()
        {
            if (!_isInitialized)
            {
                try
                {
                    _db = ObservablesContext.CreateDefault();

                    _db.EventTypes.ToList();

                    foreach (var type in _db.EventTypes)
                    {
                        _eventTypesGuids.Add((EventTypes)type.Code, type);
                    }

                    _isInitialized = true;
                }
                catch
                {
                    _isInitialized = false;
                }
            }
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Handle the application manager connected machine changed event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="machine">The machine.</param>
        private void _application_ConnectedMachineChanged(object sender, IExternalBridgeClient machine)
        {
            if (machine != null)
            {
                if (machine.MachineEventsStateProvider != null)
                {
                    machine.MachineEventsStateProvider.NewEvents -= MachineEventsStateProvider_NewEvents;
                    machine.MachineEventsStateProvider.NewEvents += MachineEventsStateProvider_NewEvents;
                    machine.MachineEventsStateProvider.EventsResolved -= MachineEventsStateProvider_EventsResolved;
                    machine.MachineEventsStateProvider.EventsResolved += MachineEventsStateProvider_EventsResolved;
                }

                machine.RequestSent -= Machine_RequestSent;
                machine.RequestFailed -= Machine_RequestFailed;
                machine.ResponseReceived -= Machine_ResponseReceived;

                machine.RequestSent += Machine_RequestSent;
                machine.RequestFailed += Machine_RequestFailed;
                machine.ResponseReceived += Machine_ResponseReceived;
            }
        }

        /// <summary>
        /// Handles the RequestSent event of the connected machine.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="message">The message.</param>
        private void Machine_RequestSent(object sender, IMessage message)
        {
            Log(EventTypes.REQUEST_SENT, String.Format("Sending request '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString()));
        }

        /// <summary>
        /// Handles the RequestFailed event of the connected machine.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RequestFailedEventArgs"/> instance containing the event data.</param>
        private void Machine_RequestFailed(object sender, RequestFailedEventArgs e)
        {
            Log(EventTypes.REQUEST_FAILED, String.Format("Request failed '{0}'...{1}{2}{1}{3}", e.Message.GetType().Name, Environment.NewLine, e.Message.ToJsonString(), e.Exception.ToString()));
        }

        /// <summary>
        /// Handles the ResponseReceived event of the connected machine.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="message">The message.</param>
        private void Machine_ResponseReceived(object sender, IMessage message)
        {
            Log(EventTypes.RESPONSE_RECEIVED, String.Format("Response received '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString()));
        }

        /// <summary>
        /// Handles the connected machine events state provider NewEvents event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="events">The events.</param>
        private void MachineEventsStateProvider_NewEvents(object sender, IEnumerable<MachinesEvent> events)
        {
            foreach (var ev in events)
            {
                Log(ev);
            }
        }

        /// <summary>
        /// Handles the connected machine events state provider EventsResolved event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="events">The events.</param>
        private void MachineEventsStateProvider_EventsResolved(object sender, IEnumerable<MachinesEvent> events)
        {
            foreach (var ev in events)
            {
                Log(String.Format("Event '{0}' resolved.", ev.EventType.Name));
            }
        }

        #endregion

        #region Logging

        /// <summary>
        /// Logs the specified machine event.
        /// </summary>
        /// <param name="machineEvent">The machine event.</param>
        public void Log(MachinesEvent machineEvent)
        {
            machineEvent.HostName = _hostName;
            machineEvent.EventType = _eventTypesGuids[machineEvent.Type];

            if (_application.ConnectedMachine == null || _authentication.CurrentUser == null)
            {
                _pendingEvents.Add(machineEvent);
            }
            else
            {
                lock (_pendingEvents)
                {
                    if (_pendingEvents.Count > 0)
                    {
                        var pending = _pendingEvents.ToList();
                        _pendingEvents.Clear();

                        foreach (var ev in pending)
                        {
                            Log(ev);
                        }
                    }
                }

                LogManager.Log("Logging event " + machineEvent.EventType.Name + " - " + machineEvent.Description);
                machineEvent.MachineGuid = _application.Machine.Guid;
                machineEvent.UserGuid = _authentication.CurrentUser.Guid;
                machineEvent.User = _authentication.CurrentUser;
                _events.Enqueue(machineEvent);
                NewLog?.Invoke(this, machineEvent);
            }
        }

        /// <summary>
        /// Logs the specified event type.
        /// </summary>
        /// <param name="eventType">Type of the event.</param>
        /// <param name="message">The message.</param>
        public void Log(EventTypes eventType, string message, bool write_to_db = true)
        {
            Init();

            MachinesEvent machineEvent = new MachinesEvent();
            machineEvent.DateTime = DateTime.UtcNow;
            machineEvent.Description = message;
            machineEvent.EventType = _eventTypesGuids[eventType];
            machineEvent.EventTypeGuid = machineEvent.EventType.Guid;

            if (write_to_db)
            {
                Log(machineEvent);
            }
            else
            {
                NewLog?.Invoke(this, machineEvent);
            }
        }

        /// <summary>
        /// Logs the specified hardware event.
        /// </summary>
        /// <param name="hardwareEvent">The hardware event.</param>
        public void Log(Event hardwareEvent)
        {
            Log((EventTypes)hardwareEvent.Type, hardwareEvent.Message);
        }

        /// <summary>
        /// Logs the specified exception using the <see cref="EventTypes.ApplicationException"/>.
        /// </summary>
        /// <param name="exception">The exception.</param>
        public void Log(Exception exception)
        {
            Log(EventTypes.APPLICATION_EXCEPTION, exception.ToString());
        }

        /// <summary>
        /// Logs the specified exception using the <see cref="EventTypes.ApplicationException" />.
        /// </summary>
        /// <param name="exception">The exception.</param>
        /// <param name="description"></param>
        public void Log(Exception exception, string description)
        {
            Log(EventTypes.APPLICATION_EXCEPTION, description + Environment.NewLine + exception.ToString());
        }

        /// <summary>
        /// Logs the specified message using the <see cref="EventTypes.ApplicationInformation"/>.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Log(String message)
        {
            Log(EventTypes.APPLICATION_INFORMATION, message);
        }

        /// <summary>
        /// Logging thread loop.
        /// </summary>
        private void LogThreadMethod()
        {
            while (true)
            {
                FlushAll();
                Thread.Sleep(5000);
            }
        }

        /// <summary>
        /// Immediately saves all pending events to database.
        /// </summary>
        public void FlushAll()
        {
            bool _saveChanges = false;

            while (_events.Count > 0)
            {
                MachinesEvent ev = null;

                if (_events.TryDequeue(out ev))
                {
                    ev.User = null;
                    _db.MachinesEvents.Add(ev);
                    _saveChanges = true;
                }
            }

            if (_saveChanges)
            {
                try
                {
                    _db.SaveChanges();
                }
                catch (Exception ex)
                {
                    LogManager.Log(ex, "Error saving machine event to database.");
                }
            }
        }

        #endregion
    }
}