using Notifications.Wpf; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Documents; using System.Windows.Input; using Tango.Core; using Tango.Core.Commands; using Tango.Logging; using Tango.Settings; using Tango.SharedUI; using Tango.SharedUI.Components; using Tango.SharedUI.Helpers; using Tango.StubsUtils.Service.UI.Views; namespace Tango.StubsUtils.Service.UI.ViewModels { public class MainViewVM : ViewModel { private ProducerConsumerQueue _logsQueue; private Thread _logsThread; private NotificationManager _notification; private ServiceUISettings _settings; public ServiceUISettings Settings { get { return _settings; } set { _settings = value; RaisePropertyChangedAuto(); } } private StubsService _service; public StubsService Service { get { return _service; } set { _service = value; RaisePropertyChangedAuto(); } } private bool _isTrayIconVisible; public bool IsTrayIconVisible { get { return _isTrayIconVisible; } set { _isTrayIconVisible = value; RaisePropertyChangedAuto(); } } private List _availablePorts; public List AvailablePorts { get { return _availablePorts; } set { _availablePorts = value; RaisePropertyChangedAuto(); } } private String _selectedPort; public String SelectedPort { get { return _selectedPort; } set { _selectedPort = value; RaisePropertyChangedAuto(); } } private SimpleStringLogger _logger; public SimpleStringLogger Logger { get { return _logger; } set { _logger = value; RaisePropertyChangedAuto(); } } public RelayCommand ExitCommand { get; set; } public RelayCommand OpenCommand { get; set; } public RelayCommand RefreshPortsCommand { get; set; } public RelayCommand ToggleConnectionCommand { get; set; } public RelayCommand ClearLogCommand { get; set; } public RelayCommand StartPerformanceTesterCommand { get; set; } public MainViewVM() { ExitCommand = new RelayCommand(ExitApplication); OpenCommand = new RelayCommand(OpenMainWindow); IsTrayIconVisible = true; AvailablePorts = new List(); RefreshPortsCommand = new RelayCommand(RefreshPorts); ToggleConnectionCommand = new RelayCommand(ToggleConnection); StartPerformanceTesterCommand = new RelayCommand(StartPerformanceTester); ClearLogCommand = new RelayCommand(ClearLog); _logsQueue = new ProducerConsumerQueue(); _logsThread = new Thread(LogsThreadMethod); _logsThread.IsBackground = true; _logsThread.Start(); _notification = new NotificationManager(); Init(); } public async void Init() { try { Logger = new SimpleStringLogger() { Enabled = true }; Logger.LogReceived += Logger_LogReceived; LogManager.RegisterLogger(Logger); LogManager.Log("Initializing..."); Settings = SettingsManager.Default.GetOrCreate(); SelectedPort = Settings.USBPort; RefreshPorts(); Service = new StubsService(); Service.CommunicationFailed += Service_CommunicationFailed; await Service.Start(); _notification.Show(new NotificationContent() { Title = "Tango Stubs Service", Message = $"Service Started", Type = NotificationType.Success }); if (Settings.AutoConnect) { await Task.Delay(2000); ToggleConnection(); } } catch (Exception ex) { LogManager.Log(ex, "Error initializing service."); _notification.Show(new NotificationContent() { Title = "Tango Stubs Service", Message = $"Initialization Error", Type = NotificationType.Error }); } } private void Service_CommunicationFailed(object sender, EventArgs e) { if (IsTrayIconVisible) { InvokeUI(() => { _notification.Show(new NotificationContent() { Title = "Tango Stubs Service", Message = $"Communication Error", Type = NotificationType.Error }); }); } } private void Logger_LogReceived(object sender, LogItemBase e) { String message = e.TimeStamp.ToString("HH:mm:ss.ff") + ": " + e.Message; _logsQueue.BlockEnqueue(message); } private void LogsThreadMethod() { while (true) { List logs = new List(); logs.Add(_logsQueue.BlockDequeue()); while (_logsQueue.Count > 0) { logs.Add(_logsQueue.BlockDequeue()); } InvokeUINow(() => { List inlines = new List(); foreach (var log in logs) { inlines.Add(new Run(log)); inlines.Add(new LineBreak()); } MainView.Instance.paragraphLog.Inlines.AddRange(inlines); if (Mouse.LeftButton != MouseButtonState.Pressed) { MainView.Instance.scrollViewerLogs.ScrollViewer?.ScrollToEnd(); } }); Thread.Sleep(200); } } private void ClearLog() { InvokeUI(() => { IsFree = false; UIHelper.DoEvents(); MainView.Instance.paragraphLog.Inlines.Clear(); IsFree = true; }); } private async void OpenMainWindow() { Application.Current.MainWindow.Visibility = Visibility.Visible; await Task.Delay(200); Application.Current.MainWindow.WindowState = WindowState.Normal; Application.Current.MainWindow.Focus(); Application.Current.MainWindow.Activate(); IsTrayIconVisible = false; } public async void ExitApplication() { IsFree = false; SaveSettings(); IsTrayIconVisible = false; UIHelper.DoEvents(); await Task.Delay(1000); Environment.Exit(0); } private void RefreshPorts() { AvailablePorts = SerialPort.GetPortNames().ToList(); if (SelectedPort == null) { SelectedPort = AvailablePorts.FirstOrDefault(); } InvalidateRelayCommands(); } private async void ToggleConnection() { try { IsFree = false; if (!Service.IsConnected) { try { await Service.Connect(SelectedPort); SaveSettings(); if (IsTrayIconVisible) { _notification.Show(new NotificationContent() { Title = "Tango Stubs Service", Message = $"Connected ({SelectedPort})", Type = NotificationType.Success }); } } catch (Exception ex) { LogManager.Log(ex, "Error connecting to the specified serial port."); if (IsTrayIconVisible) { _notification.Show(new NotificationContent() { Title = "Tango Stubs Service", Message = $"Connection Error ({SelectedPort})", Type = NotificationType.Error }); } } } else { try { await Service.Disconnect(); } catch (Exception ex) { LogManager.Log(ex, "Error disconnecting from the specified serial port."); } } } finally { IsFree = true; } } private void SaveSettings() { Settings.USBPort = SelectedPort; Settings.Save(); } private void StartPerformanceTester() { Process.Start("tangostub_perf.exe"); } } }