From d48b2d23515d06a21ad241380986bf8f31773195 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Sun, 22 Mar 2020 00:04:44 +0200 Subject: Implemented WebRtcTransportAdapter. Implemented FileSystem via WebRTC. Improved FileSystemControl keyboard control. Implemented FileSystemControl context menu. Improved Transported custom request handler registration. Implemented FS copy/move/delete. Implemented InputBox. --- Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj') diff --git a/Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj b/Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj index 733493f02..a1218f12d 100644 --- a/Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj +++ b/Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj @@ -58,6 +58,14 @@ + + + + + + + + MSBuild:Compile -- cgit v1.3.1 From 42c06402ff6648c356fba8315958283762ed2542 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Wed, 25 Mar 2020 00:26:47 +0200 Subject: Added Download menu implementation to file system. Added several stun and turn servers to web rtc. --- .../ViewModels/FileSystemViewVM.cs | 53 ++++++++++++++++++++++ .../Tango.FSE.PPCConsole/Views/FileSystemView.xaml | 17 ++++++- .../Controls/FileSystemControl.xaml | 11 ++++- .../FileSystem/IFileSystemProvider.cs | 1 + .../FileSystem/DefaultFileSystemProvider.cs | 11 +++++ .../Tango.FSE.UI/Storage/DefaultStorageProvider.cs | 2 +- .../FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs | 4 +- .../FileSystem/DefaultFileSystemService.cs | 14 ++++++ .../Visual_Studio/PPC/Tango.PPC.UI/app.manifest | 2 +- .../Tango.FileSystem/FileExplorerControl.cs | 53 ++++++++++++++++++++-- .../Tango.FileSystem/FileSystemManager.cs | 17 +++++++ .../Network/CreateFolderRequest.cs | 14 ++++++ .../Network/CreateFolderResponse.cs | 13 ++++++ .../Tango.FileSystem/Tango.FileSystem.csproj | 2 + .../Visual_Studio/Tango.WebRTC/WebRtcClient.cs | 17 +++++++ 15 files changed, 219 insertions(+), 12 deletions(-) create mode 100644 Software/Visual_Studio/Tango.FileSystem/Network/CreateFolderRequest.cs create mode 100644 Software/Visual_Studio/Tango.FileSystem/Network/CreateFolderResponse.cs (limited to 'Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj') diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs index 4e2ca1882..e10cc0ad1 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs @@ -58,6 +58,7 @@ namespace Tango.FSE.PPCConsole.ViewModels public RelayCommand> CutPasteCommand { get; set; } public RelayCommand> DownloadCommand { get; set; } public RelayCommand RenameCommand { get; set; } + public RelayCommand NewFolderCommand { get; set; } public FileSystemViewVM() @@ -78,6 +79,7 @@ namespace Tango.FSE.PPCConsole.ViewModels CutPasteCommand = new RelayCommand>((items) => PasteItems(items, true)); DownloadCommand = new RelayCommand>(DownloadSelectedItems); RenameCommand = new RelayCommand(RenameFileSystemItem); + NewFolderCommand = new RelayCommand(CreateNewFolder); } private async void NavigateBack() @@ -341,7 +343,24 @@ namespace Tango.FSE.PPCConsole.ViewModels var result = await StorageProvider.SelectFolder("Select download destination folder"); if (result) { + + String destination = result.SelectedItem; + Debug.WriteLine($"Download to {result.SelectedItem}"); + + foreach (var item in items.Where(x => x.Type != FileSystemItemType.Drive)) + { + if (File.Exists(Path.Combine(destination, item.Name)) || Directory.Exists(Path.Combine(destination, item.Name))) + { + if (!await NotificationProvider.ShowWarningQuestion($"'{item.Name}' already exists on '{Path.GetDirectoryName(destination)}'. Do you want to overwrite?")) + { + continue; + } + } + + var handler = await FileSystemProvider.Download(item, destination); + FileSystemHandlers.Insert(0, handler); + } } } @@ -376,6 +395,40 @@ namespace Tango.FSE.PPCConsole.ViewModels } } + private async void CreateNewFolder() + { + if (CurrentItem == null) return; + if (CurrentItem is FolderItem) + { + if ((CurrentItem as FolderItem).IsRoot) return; + } + + var result = await NotificationProvider.ShowInputBox( + "New Folder", + $"Please enter a folder name and press 'ENTER'.", + PackIconKind.FolderAdd, "untitled", + "folder name", + 100, + "CREATE"); + + if (result.Confirmed) + { + try + { + using (NotificationProvider.PushTaskItem("Creating new folder...")) + { + var folderItem = await FileSystemProvider.CreateFolder(CurrentItem, result.Input); + NavigateToCurrentPath(); //Instead of inserting folder item just refresh the current path... + } + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error creating new folder '{Path.Combine(CurrentItem.Path,result.Input)}."); + await NotificationProvider.ShowError($"Error creating folder '{result.Input}'.\n{ex.FlattenMessage()}"); + } + } + } + private void OnCurrentItemChanged() { CurrentPath = CurrentItem.Path; diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/FileSystemView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/FileSystemView.xaml index d1143ede4..67f1dc1c5 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/FileSystemView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/FileSystemView.xaml @@ -121,6 +121,7 @@ + RenameCommand="{Binding RenameCommand}" + NewFolderCommand="{Binding NewFolderCommand}"/> @@ -163,7 +165,18 @@ - + + + + + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml index eb1007609..5bc75ca54 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml @@ -49,6 +49,13 @@ + + + + + + + @@ -93,7 +100,7 @@ - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/ExplorerControlDialog.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/ExplorerControlDialog.xaml.cs new file mode 100644 index 000000000..db12a70f1 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/ExplorerControlDialog.xaml.cs @@ -0,0 +1,218 @@ +using Microsoft.WindowsAPICodePack.Controls; +using Microsoft.WindowsAPICodePack.Shell; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace Tango.FSE.UI.Storage +{ + /// + /// Interaction logic for ExplorerControlWindow.xaml + /// + public partial class ExplorerControlDialog : Window + { + private static string _lastDirectory; + private static Point? _lastLocation; + + private string _currentLocation; + + public List SelectedItems { get; set; } + public String InitialDirectory { get; set; } + + public ObservableCollection ShellHistory + { + get { return (ObservableCollection)GetValue(ShellHistoryProperty); } + set { SetValue(ShellHistoryProperty, value); } + } + public static readonly DependencyProperty ShellHistoryProperty = + DependencyProperty.Register("ShellHistory", typeof(ObservableCollection), typeof(ExplorerControlDialog), new PropertyMetadata(null)); + + public ExplorerControlDialog() + { + SelectedItems = new List(); + ShellHistory = new ObservableCollection(); + + InitializeComponent(); + Loaded += ExplorerControlWindow_Loaded; + SourceInitialized += ExplorerControlWindow_SourceInitialized; + explorer.browser.SelectionChanged += Browser_SelectionChanged; + explorer.browser.NavigationComplete += Browser_NavigationComplete; + btnSelect.IsEnabled = false; + btnBack.IsEnabled = false; + btnForward.IsEnabled = false; + + if (_lastLocation != null) + { + WindowStartupLocation = WindowStartupLocation.Manual; + Left = _lastLocation.Value.X; + Top = _lastLocation.Value.Y; + } + else + { + WindowStartupLocation = WindowStartupLocation.CenterOwner; + } + } + + private void FillShellHistory(ShellObject current) + { + ShellHistory.Clear(); + + ShellObject parent = current; + + while (parent != null) + { + ShellHistory.Insert(0, parent); + + if (parent.ToString() == "This PC") break; + + parent = parent.Parent; + } + } + + private void Browser_NavigationComplete(object sender, Microsoft.WindowsAPICodePack.Controls.NavigationCompleteEventArgs e) + { + _currentLocation = e.NewLocation.ParsingName; + ShellObject shell = ShellObject.FromParsingName(_currentLocation); + + if (shell.ToString() != "This PC") + { + btnUp.IsEnabled = true; + txtLocation.Text = shell.GetDisplayName(DisplayNameType.FileSystemPath); + } + else + { + btnUp.IsEnabled = false; + txtLocation.Text = ""; + } + + FillShellHistory(shell); + + btnBack.IsEnabled = explorer.browser.NavigationLog.CanNavigateBackward; + btnForward.IsEnabled = explorer.browser.NavigationLog.CanNavigateForward; + } + + private void Browser_SelectionChanged(object sender, EventArgs e) + { + if (explorer.browser.SelectedItems.OfType().ToList().Count > 0) + { + btnSelect.IsEnabled = true; + } + else + { + btnSelect.IsEnabled = false; + } + } + + private void ExplorerControlWindow_SourceInitialized(object sender, EventArgs e) + { + this.HideMinimizeAndMaximizeButtons(); + } + + private void ExplorerControlWindow_Loaded(object sender, RoutedEventArgs e) + { + ShellObject initialShellObject = (ShellObject)KnownFolders.Desktop; + + if (InitialDirectory != null && Directory.Exists(InitialDirectory)) + { + initialShellObject = ShellObject.FromParsingName(InitialDirectory); + } + else if (_lastDirectory != null && Directory.Exists(_lastDirectory)) + { + initialShellObject = ShellObject.FromParsingName(_lastDirectory); + } + + explorer.browser.Navigate(initialShellObject); + } + + private void BtnSelect_Click(object sender, RoutedEventArgs e) + { + SelectedItems.Clear(); + + foreach (var item in explorer.browser.SelectedItems.OfType()) + { + SelectedItems.Add(item.ParsingName); + } + + _lastDirectory = _currentLocation; + _lastLocation = new Point(Left, Top); + + + DialogResult = true; + Close(); + } + + private void BtnCancel_Click(object sender, RoutedEventArgs e) + { + _lastLocation = new Point(Left, Top); + Close(); + } + + private void BtnBack_Click(object sender, RoutedEventArgs e) + { + explorer.browser.NavigateLogLocation(NavigationLogDirection.Backward); + } + + private void BtnForward_Click(object sender, RoutedEventArgs e) + { + explorer.browser.NavigateLogLocation(NavigationLogDirection.Forward); + } + + private void BtnUp_Click(object sender, RoutedEventArgs e) + { + ShellObject currentLocation = ShellObject.FromParsingName(_currentLocation); + explorer.browser.Navigate(currentLocation.Parent); + } + + private void TxtLocation_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) + { + listHistory.Visibility = Visibility.Collapsed; + } + + private void TxtLocation_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) + { + listHistory.Visibility = Visibility.Visible; + } + + private void OnHistoryItemClicked(object sender, RoutedEventArgs e) + { + ShellObject shell = (sender as Button).DataContext as ShellObject; + explorer.browser.Navigate(shell); + } + } + + internal static class WindowExtensions + { + // from winuser.h + private const int GWL_STYLE = -16, + WS_MAXIMIZEBOX = 0x10000, + WS_MINIMIZEBOX = 0x20000; + + [DllImport("user32.dll")] + extern private static int GetWindowLong(IntPtr hwnd, int index); + + [DllImport("user32.dll")] + extern private static int SetWindowLong(IntPtr hwnd, int index, int value); + + internal static void HideMinimizeAndMaximizeButtons(this Window window) + { + IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(window).Handle; + var currentStyle = GetWindowLong(hwnd, GWL_STYLE); + + SetWindowLong(hwnd, GWL_STYLE, (currentStyle & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX)); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/ExplorerControlForms.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/ExplorerControlForms.cs new file mode 100644 index 000000000..928baa201 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/ExplorerControlForms.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Tango.FSE.Storage.UI +{ + public partial class ExplorerControlForms : UserControl + { + public ExplorerControlForms() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/ExplorerControlForms.designer.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/ExplorerControlForms.designer.cs new file mode 100644 index 000000000..f77fdd5cc --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/ExplorerControlForms.designer.cs @@ -0,0 +1,109 @@ +namespace Tango.FSE.Storage.UI +{ + partial class ExplorerControlForms + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.browser = new Microsoft.WindowsAPICodePack.Controls.WindowsForms.ExplorerBrowser(); + this.panel1 = new System.Windows.Forms.Panel(); + this.panel2 = new System.Windows.Forms.Panel(); + this.panel3 = new System.Windows.Forms.Panel(); + this.panel4 = new System.Windows.Forms.Panel(); + this.SuspendLayout(); + // + // browser + // + this.browser.Dock = System.Windows.Forms.DockStyle.Fill; + this.browser.Location = new System.Drawing.Point(0, 0); + this.browser.Name = "browser"; + this.browser.PropertyBagName = "Microsoft.WindowsAPICodePack.Controls.WindowsForms.ExplorerBrowser"; + this.browser.Size = new System.Drawing.Size(398, 311); + this.browser.TabIndex = 1; + // + // panel1 + // + this.panel1.BackColor = System.Drawing.Color.White; + this.panel1.Dock = System.Windows.Forms.DockStyle.Top; + this.panel1.Location = new System.Drawing.Point(0, 0); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(398, 1); + this.panel1.TabIndex = 2; + // + // panel2 + // + this.panel2.BackColor = System.Drawing.Color.White; + this.panel2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.panel2.Location = new System.Drawing.Point(0, 310); + this.panel2.Margin = new System.Windows.Forms.Padding(0); + this.panel2.Name = "panel2"; + this.panel2.Size = new System.Drawing.Size(398, 1); + this.panel2.TabIndex = 3; + // + // panel3 + // + this.panel3.BackColor = System.Drawing.Color.White; + this.panel3.Dock = System.Windows.Forms.DockStyle.Left; + this.panel3.Location = new System.Drawing.Point(0, 1); + this.panel3.Margin = new System.Windows.Forms.Padding(0); + this.panel3.Name = "panel3"; + this.panel3.Size = new System.Drawing.Size(1, 309); + this.panel3.TabIndex = 4; + // + // panel4 + // + this.panel4.BackColor = System.Drawing.Color.White; + this.panel4.Dock = System.Windows.Forms.DockStyle.Right; + this.panel4.Location = new System.Drawing.Point(397, 1); + this.panel4.Margin = new System.Windows.Forms.Padding(0); + this.panel4.Name = "panel4"; + this.panel4.Size = new System.Drawing.Size(1, 309); + this.panel4.TabIndex = 5; + // + // ExplorerControlForms + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.panel4); + this.Controls.Add(this.panel3); + this.Controls.Add(this.panel2); + this.Controls.Add(this.panel1); + this.Controls.Add(this.browser); + this.Name = "ExplorerControlForms"; + this.Size = new System.Drawing.Size(398, 311); + this.ResumeLayout(false); + + } + + #endregion + + public Microsoft.WindowsAPICodePack.Controls.WindowsForms.ExplorerBrowser browser; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Panel panel2; + private System.Windows.Forms.Panel panel3; + private System.Windows.Forms.Panel panel4; + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/ExplorerControlForms.resx b/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/ExplorerControlForms.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/ExplorerControlForms.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj index 12b4c9d45..b4854db5a 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj @@ -53,6 +53,9 @@ ..\..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.dll + + ..\..\packages\Ionic.Zip.1.9.1.8\lib\Ionic.Zip.dll + ..\..\packages\MahApps.Metro.1.6.5\lib\net46\MahApps.Metro.dll @@ -110,6 +113,7 @@ + @@ -169,6 +173,15 @@ + + ExplorerControlDialog.xaml + + + UserControl + + + ExplorerControlForms.cs + @@ -248,6 +261,10 @@ Designer MSBuild:Compile + + MSBuild:Compile + Designer + MSBuild:Compile Designer @@ -299,6 +316,9 @@ ResXFileCodeGenerator Resources.Designer.cs + + ExplorerControlForms.cs + SettingsSingleFileGenerator diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs index 9ed73afb2..130839534 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs @@ -178,7 +178,7 @@ namespace Tango.FSE.UI.ViewModels private void DiagnosticsProvider_FrameReceived(object sender, Common.Diagnostics.DiagnosticsFrameReceivedEventArgs e) { - Debug.WriteLine("Diagnostics Received..."); + //Debug.WriteLine("Diagnostics Received..."); } private void Logout() diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml index 6941b830a..0f16697ad 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml @@ -579,6 +579,10 @@ + + + + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config b/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config index fda2f4d3f..a55bb6f29 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config @@ -4,6 +4,7 @@ + diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs index acdf20fa8..1c0c52196 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs @@ -34,6 +34,7 @@ namespace Tango.PPC.Common.Connection private bool _isInitialized; private Thread _connection_thread; private ObservablesContext _context; + private bool disableConnectionFileLogging; private Machine _machine; /// @@ -106,11 +107,18 @@ namespace Tango.PPC.Common.Connection { if (MachineOperator.State != TransportComponentState.Connected) { + var fileLogger = LogManager.RegisteredLoggers.FirstOrDefault(x => x.GetType() == typeof(FileLogger)); + try { Thread.Sleep(2000); - LogManager.Log("Starting machine connection procedure...", LogCategory.Debug); + if (fileLogger != null && disableConnectionFileLogging) + { + fileLogger.Enabled = false; + } + + LogManager.Log("Starting machine connection procedure...", LogCategory.Info); var settings = SettingsManager.Default.GetOrCreate(); @@ -120,19 +128,19 @@ namespace Tango.PPC.Common.Connection { TimeSpan timeout = TimeSpan.FromSeconds(SettingsManager.Default.GetOrCreate().MachineScanningTimeoutSeconds); - LogManager.Log("Scanning for machine on available serial ports...", LogCategory.Debug); + LogManager.Log("Scanning for machine on available serial ports...", LogCategory.Info); Transport.Discovery.UsbCommunicationScanner scanner = new Transport.Discovery.UsbCommunicationScanner(UsbSerialBaudRates.BR_115200); var response = await scanner.Scan(new ConnectRequest() { Password = "1234" }, settings.EmbeddedDeviceHint, timeout); - LogManager.Log("Machine discovered on port: " + response.Adapter.Address, LogCategory.Debug); + LogManager.Log("Machine discovered on port: " + response.Adapter.Address, LogCategory.Info); LogManager.Log("Device Information:", LogCategory.Debug); - LogManager.Log(response.Response.DeviceInformation.ToJsonString(), LogCategory.Debug); + LogManager.Log(response.Response.DeviceInformation.ToJsonString(), LogCategory.Info); - LogManager.Log("Disconnecting machine operator...", LogCategory.Debug); + LogManager.Log("Disconnecting machine operator...", LogCategory.Info); await MachineOperator.Disconnect(); MachineOperator.Adapter = response.Adapter; MachineOperator.JobHandlingMode = JobHandlerModes.SettingUp; - LogManager.Log("Connecting machine operator...", LogCategory.Debug); + LogManager.Log("Connecting machine operator...", LogCategory.Info); try { await MachineOperator.Connect(); @@ -142,6 +150,8 @@ namespace Tango.PPC.Common.Connection settings.FirmwareVersion = MachineOperator.DeviceInformation.Version; settings.Save(); } + + disableConnectionFileLogging = false; } catch (Exception) { @@ -156,7 +166,7 @@ namespace Tango.PPC.Common.Connection } else { - LogManager.Log($"Connecting to machine on {settings.EmbeddedComPort}...", LogCategory.Debug); + LogManager.Log($"Connecting to machine on {settings.EmbeddedComPort}...", LogCategory.Info); UsbTransportAdapter adapter = new UsbTransportAdapter(settings.EmbeddedComPort, UsbSerialBaudRates.BR_115200); MachineOperator.Adapter = adapter; @@ -170,6 +180,8 @@ namespace Tango.PPC.Common.Connection settings.FirmwareVersion = MachineOperator.DeviceInformation.Version; settings.Save(); } + + disableConnectionFileLogging = false; } catch (Exception) { @@ -200,6 +212,8 @@ namespace Tango.PPC.Common.Connection LogManager.Log("Connecting machine operator..."); await MachineOperator.Connect(); + disableConnectionFileLogging = false; + if (MachineOperator.DeviceInformation != null) { settings.FirmwareVersion = MachineOperator.DeviceInformation.Version; @@ -212,7 +226,18 @@ namespace Tango.PPC.Common.Connection } catch (Exception ex) { - LogManager.Log(ex, LogCategory.Debug, "Error while trying to scan and connect to the machine."); + LogManager.Log(ex, "Error while trying to scan and connect to the machine."); + LogManager.Log("File logging of further connection attempts is now disabled and will resume when connection is successful."); + disableConnectionFileLogging = true; + } + finally + { + await Task.Delay(100); + + if (fileLogger != null) + { + fileLogger.Enabled = true; + } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/FileSystem/DefaultFileSystemService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/FileSystem/DefaultFileSystemService.cs index edb004344..a7f77855a 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/FileSystem/DefaultFileSystemService.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/FileSystem/DefaultFileSystemService.cs @@ -33,6 +33,7 @@ namespace Tango.PPC.Common.FileSystem public String Id { get; set; } public String Path { get; set; } public bool IsPathTempZip { get; set; } + public String UploadPostPath { get; set; } public FileSystemOperation(FileSystemOperationMode mode, String path) { @@ -84,6 +85,7 @@ namespace Tango.PPC.Common.FileSystem webRtcTransporter.ComponentName = "File System Passive WebRTC Transporter"; webRtcTransporter.UseKeepAlive = false; webRtcTransporter.RegisterRequestHandler(WebRtcChunkDownloadRequestReceived); + webRtcTransporter.RegisterRequestHandler(WebRtcChunkUploadRequestReceived); await webRtcTransporter.Connect(); await receiver.SendGenericResponse(new InitWebRtcResponse(), token); _webRtcClients[receiver] = webRtcTransporter; @@ -99,6 +101,11 @@ namespace Tango.PPC.Common.FileSystem OnChunkDownloadRequest(request, token, transporter); } + private void WebRtcChunkUploadRequestReceived(ITransporter transporter, ChunkUploadRequest request, string token) + { + OnChunkUploadRequest(request, token, transporter); + } + [ExternalBridgeRequestHandlerMethod(typeof(GetFileSystemItemRequest))] public async void OnGetFileSystemItemRequest(GetFileSystemItemRequest request, String token, ExternalBridgeReceiver receiver) { @@ -118,9 +125,10 @@ namespace Tango.PPC.Common.FileSystem { try { - using (var stream = new FileStream(request.Path, FileMode.Create)) { } + var tempFile = TemporaryManager.CreateFile(); + using (var stream = new FileStream(tempFile, FileMode.Create)) { } - FileSystemOperation operation = new FileSystemOperation(FileSystemOperationMode.Upload, request.Path); + FileSystemOperation operation = new FileSystemOperation(FileSystemOperationMode.Upload, tempFile) { UploadPostPath = request.Path }; _operations.Add(operation.Id, operation); await receiver.SendGenericResponse(new FileUploadResponse() { OperationId = operation.Id }, token); @@ -131,6 +139,25 @@ namespace Tango.PPC.Common.FileSystem } } + [ExternalBridgeRequestHandlerMethod(typeof(FolderUploadRequest))] + public async void OnFolderUploadRequest(FolderUploadRequest request, String token, ExternalBridgeReceiver receiver) + { + try + { + var tempFile = TemporaryManager.CreateFile(); + using (var stream = new FileStream(tempFile, FileMode.Create)) { } + + FileSystemOperation operation = new FileSystemOperation(FileSystemOperationMode.Upload, tempFile) { UploadPostPath = request.Path, IsPathTempZip = true }; + _operations.Add(operation.Id, operation); + + await receiver.SendGenericResponse(new FolderUploadResponse() { OperationId = operation.Id }, token); + } + catch (Exception ex) + { + await receiver.SendErrorResponse(ex, token); + } + } + [ExternalBridgeRequestHandlerMethod(typeof(FileDownloadRequest))] public async void OnFileDownloadRequest(FileDownloadRequest request, String token, ExternalBridgeReceiver receiver) { @@ -191,7 +218,7 @@ namespace Tango.PPC.Common.FileSystem } [ExternalBridgeRequestHandlerMethod(typeof(ChunkUploadRequest))] - public async void OnChunkUploadRequest(ChunkUploadRequest request, String token, ExternalBridgeReceiver receiver) + public async void OnChunkUploadRequest(ChunkUploadRequest request, String token, ITransporter receiver) { try { @@ -209,6 +236,32 @@ namespace Tango.PPC.Common.FileSystem stream.Write(request.Data, 0, request.Data.Length); } + if (request.IsCompleted) + { + if (!operation.IsPathTempZip) + { + File.Copy(operation.Path, operation.UploadPostPath, true); + try + { + File.Delete(operation.Path); + } + catch { } + } + else + { + using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile(operation.Path)) + { + zip.ExtractAll(operation.UploadPostPath, Ionic.Zip.ExtractExistingFileAction.OverwriteSilently); + } + + try + { + File.Delete(operation.Path); + } + catch { } + } + } + await receiver.SendGenericResponse(new ChunkUploadResponse(), token, new TransportResponseConfig() { Priority = QueuePriority.Low }); } catch (Exception ex) @@ -230,12 +283,19 @@ namespace Tango.PPC.Common.FileSystem } FileStream stream = null; + bool removeTempZipFile = false; try { stream = new FileStream(operation.Path, FileMode.Open); stream.Position = request.Position; byte[] data = new byte[Math.Min(request.MaxChunkSize, stream.Length - stream.Position)]; + + if (stream.Position + data.Length == stream.Length) + { + removeTempZipFile = true; + } + await stream.ReadAsync(data, 0, data.Length); stream.Dispose(); stream = null; @@ -249,6 +309,20 @@ namespace Tango.PPC.Common.FileSystem stream?.Dispose(); await receiver.SendErrorResponse(ex, token); } + finally + { + if (operation.IsPathTempZip && removeTempZipFile) + { + try + { + if (File.Exists(operation.Path)) + { + File.Delete(operation.Path); + } + } + catch { } + } + } } [ExternalBridgeRequestHandlerMethod(typeof(AbortOperationRequest))] @@ -271,10 +345,6 @@ namespace Tango.PPC.Common.FileSystem { File.Delete(operation.Path); } - else if (Directory.Exists(operation.Path)) - { - Directory.Delete(operation.Path, true); - } } else if (operation.IsPathTempZip) { @@ -348,6 +418,20 @@ namespace Tango.PPC.Common.FileSystem } } + [ExternalBridgeRequestHandlerMethod(typeof(PerformDiskSpaceOptimizationRequest))] + public async void OnPerformDiskSpaceOptimizationRequest(PerformDiskSpaceOptimizationRequest request, String token, ExternalBridgeReceiver receiver) + { + try + { + var deletedBytes = _manager.PerformDiskSpaceOptimization(); + await receiver.SendGenericResponse(new PerformDiskSpaceOptimizationResponse() { DeletedBytes = deletedBytes }, token); + } + catch (Exception ex) + { + await receiver.SendErrorResponse(ex, token); + } + } + public void OnReceiverDisconnected(ExternalBridgeReceiver receiver) { if (_webRtcClients.ContainsKey(receiver)) diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/app.manifest b/Software/Visual_Studio/PPC/Tango.PPC.UI/app.manifest index d72e75011..efc5f8179 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/app.manifest +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/app.manifest @@ -16,7 +16,7 @@ Remove this element if your application requires this virtualization for backwards compatibility. --> - + diff --git a/Software/Visual_Studio/Tango.Core/Helpers/FileHelper.cs b/Software/Visual_Studio/Tango.Core/Helpers/FileHelper.cs index 0b65de64d..8ee0f4b8f 100644 --- a/Software/Visual_Studio/Tango.Core/Helpers/FileHelper.cs +++ b/Software/Visual_Studio/Tango.Core/Helpers/FileHelper.cs @@ -16,7 +16,7 @@ namespace Tango.Core.Helpers long bytes = Math.Abs(fileSize); int place = System.Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024))); double num = Math.Round(bytes / Math.Pow(1024, place), 1); - return (Math.Sign(fileSize) * num).ToString() + suf[place]; + return (Math.Sign(fileSize) * num).ToString() + " " + suf[place]; } } } diff --git a/Software/Visual_Studio/Tango.FileSystem/FileExplorerControl.cs b/Software/Visual_Studio/Tango.FileSystem/FileExplorerControl.cs index 3660a18f0..0769b3576 100644 --- a/Software/Visual_Studio/Tango.FileSystem/FileExplorerControl.cs +++ b/Software/Visual_Studio/Tango.FileSystem/FileExplorerControl.cs @@ -233,6 +233,22 @@ namespace Tango.FileSystem public static readonly DependencyProperty RenameCommandInternalProperty = DependencyProperty.Register("RenameCommandInternal", typeof(ICommand), typeof(FileExplorerControl), new PropertyMetadata(null)); + public ICommand UploadCommandInternal + { + get { return (ICommand)GetValue(UploadCommandInternalProperty); } + set { SetValue(UploadCommandInternalProperty, value); } + } + public static readonly DependencyProperty UploadCommandInternalProperty = + DependencyProperty.Register("UploadCommandInternal", typeof(ICommand), typeof(FileExplorerControl), new PropertyMetadata(null)); + + public ICommand UploadCommand + { + get { return (ICommand)GetValue(UploadCommandProperty); } + set { SetValue(UploadCommandProperty, value); } + } + public static readonly DependencyProperty UploadCommandProperty = + DependencyProperty.Register("UploadCommand", typeof(ICommand), typeof(FileExplorerControl), new PropertyMetadata(null)); + public bool IsContextMenuOpened { get { return (bool)GetValue(IsContextMenuOpenedProperty); } @@ -395,6 +411,11 @@ namespace Tango.FileSystem return true; }); + + UploadCommandInternal = new RelayCommand(() => + { + UploadCommand?.Execute(null); + }); } private void OnIsContextMenuOpenedChanged() @@ -408,6 +429,7 @@ namespace Tango.FileSystem (DeleteCommandInternal as RelayCommand)?.RaiseCanExecuteChanged(); (RenameCommandInternal as RelayCommand)?.RaiseCanExecuteChanged(); (NewFolderCommandInternal as RelayCommand)?.RaiseCanExecuteChanged(); + (UploadCommandInternal as RelayCommand)?.RaiseCanExecuteChanged(); if (IsContextMenuOpened) { @@ -808,6 +830,7 @@ namespace Tango.FileSystem try { + Debug.WriteLine("Drag Started..."); var ef = DragDrop.DoDragDrop(this, new DataObject(DataFormats.FileDrop, files, false), DragDropEffects.Copy); } catch (Exception ex) @@ -816,6 +839,8 @@ namespace Tango.FileSystem Debugger.Break(); } + Debug.WriteLine("Drag Stopped..."); + await Task.Delay(3000); foreach (var watcher in watchers) @@ -838,6 +863,7 @@ namespace Tango.FileSystem { if (IsVisible) { + AllowDrop = true; await Task.Delay(100); this.Focus(); Keyboard.Focus(this); diff --git a/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs b/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs index 46ca080a2..c08304ca8 100644 --- a/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs +++ b/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs @@ -7,6 +7,7 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using Tango.Core.Helpers; using Tango.FileSystem.Network; +using Tango.Logging; namespace Tango.FileSystem { @@ -22,7 +23,7 @@ namespace Tango.FileSystem { Path = x.RootDirectory.FullName, DriveType = x.DriveType, - DriveLabel = x.Name, + DriveLabel = $"{x.VolumeLabel} ({x.Name.Replace("\\", "")})", Type = FileSystemItemType.Drive, }).Cast().ToList(); @@ -198,5 +199,61 @@ namespace Tango.FileSystem Path = fullPath }); } + + public long PerformDiskSpaceOptimization() + { + var tempDir = Path.GetTempPath(); + var logsFolder = FileLogger.DefaultLogsFolder; + + long sizeBefore = GetDirectorySize(new DirectoryInfo(tempDir)) + GetDirectorySize(new DirectoryInfo(logsFolder)); + + foreach (var file in Directory.GetFiles(tempDir, "*.*", SearchOption.AllDirectories)) + { + try + { + FileInfo fileInfo = new FileInfo(file); + if (fileInfo.LastWriteTime < DateTime.Now.AddDays(-1)) + { + File.Delete(file); + } + } + catch { } + } + + foreach (var file in Directory.GetFiles(logsFolder, "*.*", SearchOption.AllDirectories)) + { + try + { + FileInfo fileInfo = new FileInfo(file); + if (fileInfo.LastWriteTime < DateTime.Now.AddDays(-2)) + { + File.Delete(file); + } + } + catch { } + } + + long sizeAfter = GetDirectorySize(new DirectoryInfo(tempDir)) + GetDirectorySize(new DirectoryInfo(logsFolder)); + + return Math.Max(sizeBefore - sizeAfter, 0); + } + + public static long GetDirectorySize(DirectoryInfo d) + { + long size = 0; + // Add file sizes. + FileInfo[] fis = d.GetFiles(); + foreach (FileInfo fi in fis) + { + size += fi.Length; + } + // Add subdirectory sizes. + DirectoryInfo[] dis = d.GetDirectories(); + foreach (DirectoryInfo di in dis) + { + size += GetDirectorySize(di); + } + return size; + } } } diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/ChunkDownloadRequest.cs b/Software/Visual_Studio/Tango.FileSystem/Network/ChunkDownloadRequest.cs index 16951930e..caedad88b 100644 --- a/Software/Visual_Studio/Tango.FileSystem/Network/ChunkDownloadRequest.cs +++ b/Software/Visual_Studio/Tango.FileSystem/Network/ChunkDownloadRequest.cs @@ -10,6 +10,6 @@ namespace Tango.FileSystem.Network { public String OperationId { get; set; } public long Position { get; set; } - public long MaxChunkSize { get; set; } = 1024 * 1024; + public long MaxChunkSize { get; set; } = 1024 * 10; } } diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/ChunkUploadRequest.cs b/Software/Visual_Studio/Tango.FileSystem/Network/ChunkUploadRequest.cs index 98a27efd2..ed6b3e45f 100644 --- a/Software/Visual_Studio/Tango.FileSystem/Network/ChunkUploadRequest.cs +++ b/Software/Visual_Studio/Tango.FileSystem/Network/ChunkUploadRequest.cs @@ -10,5 +10,6 @@ namespace Tango.FileSystem.Network { public String OperationId { get; set; } public byte[] Data { get; set; } + public bool IsCompleted { get; set; } } } diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/FolderUploadRequest.cs b/Software/Visual_Studio/Tango.FileSystem/Network/FolderUploadRequest.cs new file mode 100644 index 000000000..79a93eff3 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Network/FolderUploadRequest.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem.Network +{ + public class FolderUploadRequest + { + public String Path { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/FolderUploadResponse.cs b/Software/Visual_Studio/Tango.FileSystem/Network/FolderUploadResponse.cs new file mode 100644 index 000000000..dc661dc95 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Network/FolderUploadResponse.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem.Network +{ + public class FolderUploadResponse + { + public String OperationId { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/PerformDiskSpaceOptimizationRequest.cs b/Software/Visual_Studio/Tango.FileSystem/Network/PerformDiskSpaceOptimizationRequest.cs new file mode 100644 index 000000000..bd69bf9d8 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Network/PerformDiskSpaceOptimizationRequest.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem.Network +{ + public class PerformDiskSpaceOptimizationRequest + { + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/PerformDiskSpaceOptimizationResponse.cs b/Software/Visual_Studio/Tango.FileSystem/Network/PerformDiskSpaceOptimizationResponse.cs new file mode 100644 index 000000000..73cbbf566 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Network/PerformDiskSpaceOptimizationResponse.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem.Network +{ + public class PerformDiskSpaceOptimizationResponse + { + public long DeletedBytes { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj b/Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj index a31af216c..d78419b7f 100644 --- a/Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj +++ b/Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj @@ -64,10 +64,14 @@ + + + + MSBuild:Compile @@ -131,6 +135,10 @@ {a34ee0f0-649d-41c8-8489-b6f1cc6924ee} Tango.Core + + {BC932DBD-7CDB-488C-99E4-F02CF441F55E} + Tango.Logging + {8491d07b-c1f6-4b62-a412-41b9fd2d6538} Tango.SharedUI diff --git a/Software/Visual_Studio/Tango.Transport/Adapters/SignalRTransportAdapter.cs b/Software/Visual_Studio/Tango.Transport/Adapters/SignalRTransportAdapter.cs index def4cd741..de472d993 100644 --- a/Software/Visual_Studio/Tango.Transport/Adapters/SignalRTransportAdapter.cs +++ b/Software/Visual_Studio/Tango.Transport/Adapters/SignalRTransportAdapter.cs @@ -30,7 +30,7 @@ namespace Tango.Transport.Adapters public String Hub { get; set; } /// - /// Gets or sets the serial number of the remote machine (Use onlt for ) mode. + /// Gets or sets the serial number of the remote machine (Use only for ) mode. /// public String SerialNumber { get; set; } @@ -66,7 +66,7 @@ namespace Tango.Transport.Adapters public SignalRTransportAdapter() : base() { ConnectionTimeout = TimeSpan.FromSeconds(30); - WriteInterval = TimeSpan.FromMilliseconds(10); + WriteInterval = TimeSpan.FromMilliseconds(1); ComponentName = $"SignalR Adapter {_component_counter++}"; } @@ -161,9 +161,10 @@ namespace Tango.Transport.Adapters { if (!completed) { + completed = true; + LogManager.Log($"SignalR adapter session created ({SessionID})..."); LogManager.Log("SingalR adapter connected."); - completed = true; State = TransportComponentState.Connected; StartPushThread(); @@ -173,8 +174,12 @@ namespace Tango.Transport.Adapters } catch (Exception ex) { - LogManager.Log(ex, "Error occurred after session created."); - completionSource.SetException(ex); + if (!completed) + { + LogManager.Log(ex, "Error occurred after session created."); + completed = true; + completionSource.SetException(ex); + } } }); } @@ -211,8 +216,12 @@ namespace Tango.Transport.Adapters } catch (Exception ex) { - LogManager.Log(ex, "Error occurred on connection state changed event."); - completionSource.SetException(ex); + if (!completed) + { + completed = true; + LogManager.Log(ex, "Error occurred on connection state changed event."); + completionSource.SetException(ex); + } } }; diff --git a/Software/Visual_Studio/Tango.Transport/Adapters/UsbTransportAdapter.cs b/Software/Visual_Studio/Tango.Transport/Adapters/UsbTransportAdapter.cs index 485eda628..4785e11c8 100644 --- a/Software/Visual_Studio/Tango.Transport/Adapters/UsbTransportAdapter.cs +++ b/Software/Visual_Studio/Tango.Transport/Adapters/UsbTransportAdapter.cs @@ -290,7 +290,6 @@ namespace Tango.Transport.Adapters { try { - LogManager.Log($"Finalizing USB transport adapter ({Address})."); _serialPort.Close(); _serialPort.Dispose(); } diff --git a/Software/Visual_Studio/Tango.Transport/ITransportAdapter.cs b/Software/Visual_Studio/Tango.Transport/ITransportAdapter.cs index d77ad1ed4..1c397aae3 100644 --- a/Software/Visual_Studio/Tango.Transport/ITransportAdapter.cs +++ b/Software/Visual_Studio/Tango.Transport/ITransportAdapter.cs @@ -15,6 +15,11 @@ namespace Tango.Transport /// public interface ITransportAdapter : ITransportComponent, INotifyPropertyChanged { + /// + /// Gets the last failed state exception/reason. + /// + Exception FailedStateException { get; } + /// /// Gets the total bytes received. /// diff --git a/Software/Visual_Studio/Tango.Transport/TransportAdapterBase.cs b/Software/Visual_Studio/Tango.Transport/TransportAdapterBase.cs index bdcf0ee64..ebae5855a 100644 --- a/Software/Visual_Studio/Tango.Transport/TransportAdapterBase.cs +++ b/Software/Visual_Studio/Tango.Transport/TransportAdapterBase.cs @@ -87,6 +87,10 @@ namespace Tango.Transport set { _address = value; RaisePropertyChangedAuto(); } } + /// + /// Gets the last failed state exception/reason. + /// + public Exception FailedStateException { get; private set; } private TransportComponentState _state; /// @@ -115,6 +119,7 @@ namespace Tango.Transport /// The ex. protected virtual void OnFailed(Exception ex) { + FailedStateException = ex; LogManager.Log(ex, $"{ComponentName}: Adapter failed."); Disconnect().Wait(); State = TransportComponentState.Failed; diff --git a/Software/Visual_Studio/Tango.Transport/TransporterBase.cs b/Software/Visual_Studio/Tango.Transport/TransporterBase.cs index 916992bc3..5e076738c 100644 --- a/Software/Visual_Studio/Tango.Transport/TransporterBase.cs +++ b/Software/Visual_Studio/Tango.Transport/TransporterBase.cs @@ -241,7 +241,7 @@ namespace Tango.Transport { if (e == TransportComponentState.Failed && FailsWithAdapter) { - OnFailed(new CommunicationException("The adapter has failed. Going into a failed state...")); + OnFailed(new CommunicationException($"The adapter has failed with exception '{Adapter.FailedStateException.Message}' and the transporter is configured to fail with the adapter.")); } } @@ -1382,6 +1382,12 @@ namespace Tango.Transport message.SetResult(true, true); } } + catch (ThreadAbortException) + { + Exception requestException = FailedStateException != null ? FailedStateException : new TransporterDisconnectedException("The transporter push thread has been aborted."); + OnRequestFailed(message, requestException); + message.SetException(requestException); + } catch (Exception ex) { OnRequestFailed(message, ex); -- cgit v1.3.1