From 539aecd793ee0ce55833eef98c3049dd0bf8127d Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Wed, 28 Nov 2018 18:10:54 +0200 Subject: Started working on Embedded Storage and machine studio Storage module. --- .../ViewModels/MainViewVM.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels') diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs new file mode 100644 index 000000000..d7eec4d36 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.MachineStudio.Common; + +namespace Tango.MachineStudio.Storage.ViewModels +{ + public class MainViewVM : StudioViewModel + { + public override void OnApplicationReady() + { + + } + } +} -- cgit v1.3.1 From ac3c227bb5d12339fee6fb4c243f3a5f67217915 Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Wed, 28 Nov 2018 20:16:11 +0200 Subject: Working on machine studio storage ! --- Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 20578304 -> 20578304 bytes .../Converters/StorageItemToImageConverter.cs | 39 ++++++ .../Helpers/FileIconHelper.cs | 146 +++++++++++++++++++++ .../Tango.MachineStudio.Storage/Images/file.png | Bin 0 -> 1184 bytes .../Tango.MachineStudio.Storage/Images/folder.png | Bin 0 -> 756 bytes .../Tango.MachineStudio.Storage.csproj | 13 +- .../ViewModels/MainViewVM.cs | 79 +++++++++++ .../Views/MainView.xaml | 126 +++++++++++++++++- .../Tango.MachineStudio.Common.csproj | 2 +- .../Tango.Emulations/Emulators/MachineEmulator.cs | 58 +++++++- .../Operation/IMachineOperator.cs | 7 + .../Tango.Integration/Operation/MachineOperator.cs | 10 ++ .../Tango.Integration/Storage/StorageFile.cs | 8 +- .../Tango.Integration/Storage/StorageItem.cs | 5 + .../Tango.Integration/Storage/StorageManager.cs | 16 +-- .../Converters/ByteArrayToFileSizeConverter.cs | 9 +- 17 files changed, 493 insertions(+), 25 deletions(-) create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Converters/StorageItemToImageConverter.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Helpers/FileIconHelper.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/file.png create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/folder.png (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels') diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index d2a861786..8aacbd172 100644 Binary files a/Software/DB/Tango.mdf and b/Software/DB/Tango.mdf differ diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf index 6485e6b4b..765615a64 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Converters/StorageItemToImageConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Converters/StorageItemToImageConverter.cs new file mode 100644 index 000000000..e9d2c8c18 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Converters/StorageItemToImageConverter.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using Tango.Integration.Storage; +using Tango.SharedUI.Helpers; + +namespace Tango.MachineStudio.Storage.Converters +{ + public class StorageItemToImageConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + StorageItem item = value as StorageItem; + + if (item != null) + { + if (item is StorageFolder) + { + return ResourceHelper.GetImageFromResources("Images/folder.png"); + } + else + { + return Helpers.FileIconHelper.FindIconForFilename(item.Name, true); + } + } + + return null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Helpers/FileIconHelper.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Helpers/FileIconHelper.cs new file mode 100644 index 000000000..47dab8e5e --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Helpers/FileIconHelper.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace Tango.MachineStudio.Storage.Helpers +{ + public static class FileIconHelper + { + private static readonly Dictionary _smallIconCache = new Dictionary(); + private static readonly Dictionary _largeIconCache = new Dictionary(); + /// + /// Get an icon for a given filename + /// + /// any filename + /// 16x16 or 32x32 icon + /// null if path is null, otherwise - an icon + public static ImageSource FindIconForFilename(string fileName, bool large) + { + var extension = Path.GetExtension(fileName); + if (extension == null) + return null; + var cache = large ? _largeIconCache : _smallIconCache; + ImageSource icon; + if (cache.TryGetValue(extension, out icon)) + return icon; + icon = IconReader.GetFileIcon(fileName, large ? IconReader.IconSize.Large : IconReader.IconSize.Small, false).ToImageSource(); + cache.Add(extension, icon); + return icon; + } + /// + /// http://stackoverflow.com/a/6580799/1943849 + /// + static ImageSource ToImageSource(this Icon icon) + { + var imageSource = Imaging.CreateBitmapSourceFromHIcon( + icon.Handle, + Int32Rect.Empty, + BitmapSizeOptions.FromEmptyOptions()); + return imageSource; + } + /// + /// Provides static methods to read system icons for both folders and files. + /// + /// + /// IconReader.GetFileIcon("c:\\general.xls"); + /// + static class IconReader + { + /// + /// Options to specify the size of icons to return. + /// + public enum IconSize + { + /// + /// Specify large icon - 32 pixels by 32 pixels. + /// + Large = 0, + /// + /// Specify small icon - 16 pixels by 16 pixels. + /// + Small = 1 + } + /// + /// Returns an icon for a given file - indicated by the name parameter. + /// + /// Pathname for file. + /// Large or small + /// Whether to include the link icon + /// System.Drawing.Icon + public static Icon GetFileIcon(string name, IconSize size, bool linkOverlay) + { + var shfi = new Shell32.Shfileinfo(); + var flags = Shell32.ShgfiIcon | Shell32.ShgfiUsefileattributes; + if (linkOverlay) flags += Shell32.ShgfiLinkoverlay; + /* Check the size specified for return. */ + if (IconSize.Small == size) + flags += Shell32.ShgfiSmallicon; + else + flags += Shell32.ShgfiLargeicon; + Shell32.SHGetFileInfo(name, + Shell32.FileAttributeNormal, + ref shfi, + (uint)Marshal.SizeOf(shfi), + flags); + // Copy (clone) the returned icon to a new object, thus allowing us to clean-up properly + var icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone(); + User32.DestroyIcon(shfi.hIcon); // Cleanup + return icon; + } + } + /// + /// Wraps necessary Shell32.dll structures and functions required to retrieve Icon Handles using SHGetFileInfo. Code + /// courtesy of MSDN Cold Rooster Consulting case study. + /// + static class Shell32 + { + private const int MaxPath = 256; + [StructLayout(LayoutKind.Sequential)] + public struct Shfileinfo + { + private const int Namesize = 80; + public readonly IntPtr hIcon; + private readonly int iIcon; + private readonly uint dwAttributes; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaxPath)] + private readonly string szDisplayName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Namesize)] + private readonly string szTypeName; + }; + public const uint ShgfiIcon = 0x000000100; // get icon + public const uint ShgfiLinkoverlay = 0x000008000; // put a link overlay on icon + public const uint ShgfiLargeicon = 0x000000000; // get large icon + public const uint ShgfiSmallicon = 0x000000001; // get small icon + public const uint ShgfiUsefileattributes = 0x000000010; // use passed dwFileAttribute + public const uint FileAttributeNormal = 0x00000080; + [DllImport("Shell32.dll")] + public static extern IntPtr SHGetFileInfo( + string pszPath, + uint dwFileAttributes, + ref Shfileinfo psfi, + uint cbFileInfo, + uint uFlags + ); + } + /// + /// Wraps necessary functions imported from User32.dll. Code courtesy of MSDN Cold Rooster Consulting example. + /// + static class User32 + { + /// + /// Provides access to function required to delete handle. This method is used internally + /// and is not required to be called separately. + /// + /// Pointer to icon handle. + /// N/A + [DllImport("User32.dll")] + public static extern int DestroyIcon(IntPtr hIcon); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/file.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/file.png new file mode 100644 index 000000000..a8cf88667 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/file.png differ diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/folder.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/folder.png new file mode 100644 index 000000000..1d32e80bf Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/folder.png differ diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage.csproj index e2f41df43..0ce2a1cb4 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage.csproj +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage.csproj @@ -43,6 +43,7 @@ + ..\..\..\packages\MahApps.Metro.1.5.0\lib\net45\System.Windows.Interactivity.dll @@ -63,6 +64,8 @@ GlobalVersionInfo.cs + + @@ -103,6 +106,10 @@ {a34ee0f0-649d-41c8-8489-b6f1cc6924ee} Tango.Core + + {4206ac58-3b57-4699-8835-90bf6db01a61} + Tango.Integration + {bc932dbd-7cdb-488c-99e4-f02cf441f55e} Tango.Logging @@ -126,9 +133,13 @@ MSBuild:Compile - + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs index d7eec4d36..f28783590 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs @@ -3,15 +3,94 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Tango.Core.Commands; +using Tango.Integration.ExternalBridge; +using Tango.Integration.Storage; using Tango.MachineStudio.Common; +using Tango.MachineStudio.Common.StudioApplication; namespace Tango.MachineStudio.Storage.ViewModels { public class MainViewVM : StudioViewModel { + private IStudioApplicationManager _applicationManager; + private bool _machine_operator_changed = true; + + private StorageManager _storageManager; + public StorageManager StorageManager + { + get { return _storageManager; } + set { _storageManager = value; RaisePropertyChangedAuto(); } + } + + private StorageItem _selectedStorageItem; + public StorageItem SelectedStorageItem + { + get { return _selectedStorageItem; } + set { _selectedStorageItem = value; RaisePropertyChangedAuto(); } + } + + private String _currentPath; + public String CurrentPath + { + get { return _currentPath; } + set { _currentPath = value; RaisePropertyChangedAuto(); } + } + + public RelayCommand BackCommand { get; set; } + + public RelayCommand RefreshCommand { get; set; } + + public RelayCommand GoCommand { get; set; } + + public MainViewVM(IStudioApplicationManager applicationManager) + { + _applicationManager = applicationManager; + _applicationManager.ConnectedMachineChanged += _applicationManager_ConnectedMachineChanged; + + GoCommand = new RelayCommand(NavigateToCurrentPath); + } + + private void _applicationManager_ConnectedMachineChanged(object sender, IExternalBridgeClient e) + { + _machine_operator_changed = true; + + if (IsVisible) + { + Initialize(); + } + } + public override void OnApplicationReady() { } + + public override void OnNavigatedTo() + { + base.OnNavigatedTo(); + + if (_machine_operator_changed) + { + _machine_operator_changed = false; + Initialize(); + } + } + + private async void NavigateToCurrentPath() + { + await StorageManager.GetFolder(CurrentPath); + } + + private async void Initialize() + { + if (_applicationManager.ConnectedMachine != null) + { + StorageManager = _applicationManager.ConnectedMachine.CreateStorageManager(); + await StorageManager.GetStorageDrive(); + await StorageManager.GetRootFolder(); + CurrentPath = StorageManager.StorageDrive.Root; + } + } } } diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml index 0350dc789..46ef31c6b 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml @@ -5,10 +5,134 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:vm="clr-namespace:Tango.MachineStudio.Storage.ViewModels" xmlns:global="clr-namespace:Tango.MachineStudio.Storage" + xmlns:mahApps="http://metro.mahapps.com/winfx/xaml/controls" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" + xmlns:localConverters="clr-namespace:Tango.MachineStudio.Storage.Converters" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:local="clr-namespace:Tango.MachineStudio.Storage.Views" mc:Ignorable="d" d:DesignHeight="1080" d:DesignWidth="1920" Background="Transparent" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}"> + + + + + + - + + + + + + ACTIONS + + + + + + + + + + + + + + + + + + + STORAGE + + + Root: + + + + Capacity: + + + + Free Space: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj index 4259bbb04..1fbd88167 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj @@ -303,7 +303,7 @@ - + \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs b/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs index 499138e0a..ae7e648f9 100644 --- a/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs +++ b/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs @@ -25,6 +25,8 @@ using Tango.BL; using Tango.PMR.Connection; using Tango.PMR.Hardware; using System.Runtime.InteropServices; +using Tango.PMR.IO; +using System.IO; namespace Tango.Emulations.Emulators { @@ -309,6 +311,12 @@ namespace Tango.Emulations.Emulators case MessageType.ResumeCurrentJobRequest: HandleResumeCurrentJobRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; + case MessageType.GetStorageInfoRequest: + HandleGetStorageInfoRequest(MessageFactory.ParseTangoMessageFromContainer(container)); + break; + case MessageType.GetFilesRequest: + HandleGetFilesRequest(MessageFactory.ParseTangoMessageFromContainer(container)); + break; } } @@ -386,7 +394,7 @@ namespace Tango.Emulations.Emulators { monitors.Dancer3Angle.Add(y); } - + var dispenserFrequencies = new RepeatedField(); @@ -957,6 +965,54 @@ namespace Tango.Emulations.Emulators } } + private void HandleGetStorageInfoRequest(TangoMessage request) + { + Transporter.SendResponse(new GetStorageInfoResponse() + { + Capacity = 1024, + FreeSpace = 500, + Root = "C:\\" + }, request.Container.Token); + } + + private void HandleGetFilesRequest(TangoMessage request) + { + String path = request.Message.Path; + + GetFilesResponse response = new GetFilesResponse(); + + foreach (var dir in Directory.GetDirectories(path)) + { + DirectoryInfo dirInfo = new DirectoryInfo(dir); + + response.Items.Add(new PMR.IO.FileInfo() + { + Attribute = FileAttribute.Directory, + FullPath = dir, + LastModifiedDate = dirInfo.LastWriteTime.DayOfYear, + LastModifiedTime = dirInfo.LastWriteTime.Hour, + Name = Path.GetFileName(dir), + }); + } + + foreach (var file in Directory.GetFiles(path)) + { + System.IO.FileInfo fileInfo = new System.IO.FileInfo(file); + + response.Items.Add(new PMR.IO.FileInfo() + { + Attribute = FileAttribute.Unspecified, + FullPath = file, + LastModifiedDate = fileInfo.LastWriteTime.DayOfYear, + LastModifiedTime = fileInfo.LastWriteTime.Hour, + Name = Path.GetFileName(file), + Length = (int)fileInfo.Length, + }); + } + + Transporter.SendResponse(response, request.Container.Token); + } + #endregion #region Public Methods diff --git a/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs index 144883abd..afbac482b 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs @@ -15,6 +15,7 @@ using Tango.BL.Entities; using Google.Protobuf; using Tango.PMR.Connection; using Tango.PMR.Stubs; +using Tango.Integration.Storage; namespace Tango.Integration.Operation { @@ -321,5 +322,11 @@ namespace Tango.Integration.Operation /// /// Task Reset(); + + /// + /// Creates a storage manager for managing the machine file system. + /// + /// + StorageManager CreateStorageManager(); } } diff --git a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs index 3b84bf09e..6b6dca4c4 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs @@ -25,6 +25,7 @@ using Tango.BL.Enumerations; using Tango.BL.ColorConversion; using Tango.PMR.Stubs; using System.Threading; +using Tango.Integration.Storage; namespace Tango.Integration.Operation { @@ -1592,6 +1593,15 @@ namespace Tango.Integration.Operation return response; } + /// + /// Creates a storage manager for managing the machine file system. + /// + /// + public StorageManager CreateStorageManager() + { + return new StorageManager(this); + } + #endregion #region Private Methods diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageFile.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageFile.cs index e2e5fb9df..069b1743d 100644 --- a/Software/Visual_Studio/Tango.Integration/Storage/StorageFile.cs +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageFile.cs @@ -3,16 +3,12 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Tango.PMR.IO; namespace Tango.Integration.Storage { public class StorageFile : StorageItem { - private int _length; - public int Length - { - get { return _length; } - set { _length = value; RaisePropertyChangedAuto(); } - } + public int Length { get; set; } } } diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageItem.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageItem.cs index a39c309e2..e8a725277 100644 --- a/Software/Visual_Studio/Tango.Integration/Storage/StorageItem.cs +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageItem.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.Core; +using Tango.PMR.IO; namespace Tango.Integration.Storage { @@ -29,5 +30,9 @@ namespace Tango.Integration.Storage return parent.FullName.Replace(parent.Root.FullName, "/").Replace("\\", "/"); } } + + public DateTime LastModified { get; set; } + + public FileAttribute Attribute { get; set; } } } diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs index 1642bd1f1..bb880f1bd 100644 --- a/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs @@ -47,20 +47,6 @@ namespace Tango.Integration.Storage #endregion - #region Commands - - /// - /// Gets or sets the back command. - /// - public RelayCommand BackCommand { get; set; } - - /// - /// Gets or sets the refresh command. - /// - public RelayCommand RefreshCommand { get; set; } - - #endregion - #region Constructor /// @@ -192,6 +178,7 @@ namespace Tango.Integration.Storage { Length = item.Length, Path = item.FullPath, + Attribute = item.Attribute, }); } else @@ -199,6 +186,7 @@ namespace Tango.Integration.Storage items.Add(new StorageFolder() { Path = item.FullPath, + Attribute = item.Attribute, }); } } diff --git a/Software/Visual_Studio/Tango.SharedUI/Converters/ByteArrayToFileSizeConverter.cs b/Software/Visual_Studio/Tango.SharedUI/Converters/ByteArrayToFileSizeConverter.cs index 91cf57c4f..5a2975535 100644 --- a/Software/Visual_Studio/Tango.SharedUI/Converters/ByteArrayToFileSizeConverter.cs +++ b/Software/Visual_Studio/Tango.SharedUI/Converters/ByteArrayToFileSizeConverter.cs @@ -16,7 +16,14 @@ namespace Tango.SharedUI.Converters { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - return BytesToString((long)value); + if (value != null) + { + return BytesToString(System.Convert.ToInt64(value)); + } + else + { + return null; + } } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) -- cgit v1.3.1 From 9e6d1ddfb42c4e8357bd75c2b1d6f84df1ea1966 Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Thu, 29 Nov 2018 13:15:09 +0200 Subject: Working on machine studio storage module. --- Software/DB/PPC/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/PPC/Tango_log.ldf | Bin 20578304 -> 20578304 bytes Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 20578304 -> 20578304 bytes Software/PMR/Messages/Common/MessageType.proto | 8 + .../PMR/Messages/IO/FileChunkDownloadRequest.proto | 1 - Software/PMR/Messages/IO/FileInfo.proto | 2 +- .../PMR/Messages/IO/GetStorageInfoResponse.proto | 4 +- .../Models/StorageFileHandlerModel.cs | 26 ++ .../Models/StorageFileHandlerType.cs | 14 + .../Tango.MachineStudio.Storage.csproj | 2 + .../ViewModels/MainViewVM.cs | 151 +++++++++- .../Views/MainView.xaml | 306 +++++++++++++++++---- .../Views/MainView.xaml.cs | 21 ++ .../Visual_Studio/Tango.Core/IO/KnownFolders.cs | 112 ++++++++ .../Visual_Studio/Tango.Core/Tango.Core.csproj | 3 +- .../Tango.Emulations/Emulators/MachineEmulator.cs | 106 +++++-- .../Tango.Integration/Storage/StorageDrive.cs | 4 +- .../Tango.Integration/Storage/StorageFile.cs | 2 +- .../Storage/StorageFileHandler.cs | 23 +- .../Storage/StorageFileHandlerStatus.cs | 17 ++ .../Tango.Integration/Storage/StorageItem.cs | 15 +- .../Tango.Integration/Storage/StorageManager.cs | 23 +- .../Tango.Integration/Tango.Integration.csproj | 1 + .../Visual_Studio/Tango.PMR/Common/MessageType.cs | 19 +- .../Tango.PMR/IO/FileChunkDownloadRequest.cs | 37 +-- Software/Visual_Studio/Tango.PMR/IO/FileInfo.cs | 20 +- .../Tango.PMR/IO/GetStorageInfoResponse.cs | 40 +-- 28 files changed, 775 insertions(+), 182 deletions(-) create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerModel.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerType.cs create mode 100644 Software/Visual_Studio/Tango.Core/IO/KnownFolders.cs create mode 100644 Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandlerStatus.cs (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels') diff --git a/Software/DB/PPC/Tango.mdf b/Software/DB/PPC/Tango.mdf index be8646788..dd1b26f08 100644 Binary files a/Software/DB/PPC/Tango.mdf and b/Software/DB/PPC/Tango.mdf differ diff --git a/Software/DB/PPC/Tango_log.ldf b/Software/DB/PPC/Tango_log.ldf index 642a4e0eb..1158f9b61 100644 Binary files a/Software/DB/PPC/Tango_log.ldf and b/Software/DB/PPC/Tango_log.ldf differ diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index 8aacbd172..243267834 100644 Binary files a/Software/DB/Tango.mdf and b/Software/DB/Tango.mdf differ diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf index 765615a64..fc2dfed0f 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/PMR/Messages/Common/MessageType.proto b/Software/PMR/Messages/Common/MessageType.proto index c39f51c86..beb1b32cd 100644 --- a/Software/PMR/Messages/Common/MessageType.proto +++ b/Software/PMR/Messages/Common/MessageType.proto @@ -226,4 +226,12 @@ enum MessageType GetStorageInfoResponse = 7013; GetFilesRequest = 7014; GetFilesResponse = 7015; + FileDownloadRequest = 7016; + FileDownloadResponse = 7017; + FileChunkDownloadRequest = 7018; + FileChunkDownloadResponse = 7019; + ValidateVersionRequest = 7020; + ValidateVersionResponse = 7021; + ActivateVersionRequest = 7022; + ActivateVersionResponse = 7023; } diff --git a/Software/PMR/Messages/IO/FileChunkDownloadRequest.proto b/Software/PMR/Messages/IO/FileChunkDownloadRequest.proto index 53442b4b0..e0b91d56a 100644 --- a/Software/PMR/Messages/IO/FileChunkDownloadRequest.proto +++ b/Software/PMR/Messages/IO/FileChunkDownloadRequest.proto @@ -8,5 +8,4 @@ message FileChunkDownloadRequest string DownloadID = 1; string FileName = 2; int64 Position = 3; - bool IsCanceled = 4; } \ No newline at end of file diff --git a/Software/PMR/Messages/IO/FileInfo.proto b/Software/PMR/Messages/IO/FileInfo.proto index 0a6581d02..43643dbda 100644 --- a/Software/PMR/Messages/IO/FileInfo.proto +++ b/Software/PMR/Messages/IO/FileInfo.proto @@ -9,7 +9,7 @@ message FileInfo { string Name = 1; string FullPath = 2; - int32 Length = 3; + int64 Length = 3; int32 LastModifiedDate = 4; int32 LastModifiedTime = 5; FileAttribute Attribute = 6; diff --git a/Software/PMR/Messages/IO/GetStorageInfoResponse.proto b/Software/PMR/Messages/IO/GetStorageInfoResponse.proto index 74b84d393..361fde488 100644 --- a/Software/PMR/Messages/IO/GetStorageInfoResponse.proto +++ b/Software/PMR/Messages/IO/GetStorageInfoResponse.proto @@ -5,7 +5,7 @@ option java_package = "com.twine.tango.pmr.io"; message GetStorageInfoResponse { - int32 Capacity = 1; - int32 FreeSpace = 2; + int64 Capacity = 1; + int64 FreeSpace = 2; string Root = 3; } \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerModel.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerModel.cs new file mode 100644 index 000000000..764512e77 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerModel.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Integration.Storage; + +namespace Tango.MachineStudio.Storage.Models +{ + public class StorageFileHandlerModel : ExtendedObject + { + public StorageFileHandler Handler { get; set; } + + public StorageFileHandlerType Type { get; set; } + + public String FilePath { get; set; } + + public StorageFileHandlerModel(StorageFileHandler handler, String filePath, StorageFileHandlerType type) + { + FilePath = filePath; + Handler = handler; + Type = type; + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerType.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerType.cs new file mode 100644 index 000000000..548b0fc86 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.MachineStudio.Storage.Models +{ + public enum StorageFileHandlerType + { + Download, + Upload + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage.csproj index 0ce2a1cb4..991e9fa2e 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage.csproj +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage.csproj @@ -66,6 +66,8 @@ + + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs index f28783590..1c6371f43 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs @@ -1,19 +1,28 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.Core.Commands; +using Tango.Core.IO; using Tango.Integration.ExternalBridge; using Tango.Integration.Storage; using Tango.MachineStudio.Common; +using Tango.MachineStudio.Common.Notifications; using Tango.MachineStudio.Common.StudioApplication; +using Tango.MachineStudio.Storage.Models; namespace Tango.MachineStudio.Storage.ViewModels { public class MainViewVM : StudioViewModel { + public event EventHandler CurrentFolderChanged; + private IStudioApplicationManager _applicationManager; + private INotificationProvider _notification; private bool _machine_operator_changed = true; private StorageManager _storageManager; @@ -43,12 +52,38 @@ namespace Tango.MachineStudio.Storage.ViewModels public RelayCommand GoCommand { get; set; } - public MainViewVM(IStudioApplicationManager applicationManager) + public RelayCommand CancelFileHandlerCommand { get; set; } + + public RelayCommand OpenFileHandlerCommand { get; set; } + + public RelayCommand RemoveFileHandlerCommand { get; set; } + + public ObservableCollection FileHandlers { get; set; } + + public MainViewVM(IStudioApplicationManager applicationManager, INotificationProvider notificationProvider) { _applicationManager = applicationManager; + _notification = notificationProvider; _applicationManager.ConnectedMachineChanged += _applicationManager_ConnectedMachineChanged; - GoCommand = new RelayCommand(NavigateToCurrentPath); + FileHandlers = new ObservableCollection(); + + GoCommand = new RelayCommand(() => NavigateToPath(CurrentPath), () => StorageManager != null); + BackCommand = new RelayCommand(NavigateBack, () => StorageManager != null && StorageManager.CurrentFolder.Parent != null); + CancelFileHandlerCommand = new RelayCommand(CancelFileHandler); + OpenFileHandlerCommand = new RelayCommand(OpenFileHandler); + RefreshCommand = new RelayCommand(Refresh, () => StorageManager != null); + RemoveFileHandlerCommand = new RelayCommand(RemoveFileHandler); + } + + private void OpenFileHandler(StorageFileHandlerModel handler) + { + ShowInExplorer(handler.FilePath); + } + + private async void CancelFileHandler(StorageFileHandlerModel handler) + { + await handler.Handler.Cancel(); } private void _applicationManager_ConnectedMachineChanged(object sender, IExternalBridgeClient e) @@ -63,7 +98,7 @@ namespace Tango.MachineStudio.Storage.ViewModels public override void OnApplicationReady() { - + } public override void OnNavigatedTo() @@ -77,19 +112,117 @@ namespace Tango.MachineStudio.Storage.ViewModels } } - private async void NavigateToCurrentPath() + private async void NavigateToPath(String path) { - await StorageManager.GetFolder(CurrentPath); + IsFree = false; + + try + { + await StorageManager.GetFolder(path); + CurrentPath = StorageManager.CurrentPath; + CurrentFolderChanged?.Invoke(this, new EventArgs()); + } + catch (Exception ex) + { + _notification.ShowError($"Error navigating to the specified path.\n{ex.Message}"); + } + + IsFree = true; + + InvalidateRelayCommands(); } private async void Initialize() { if (_applicationManager.ConnectedMachine != null) { - StorageManager = _applicationManager.ConnectedMachine.CreateStorageManager(); - await StorageManager.GetStorageDrive(); - await StorageManager.GetRootFolder(); - CurrentPath = StorageManager.StorageDrive.Root; + try + { + StorageManager = _applicationManager.ConnectedMachine.CreateStorageManager(); + await StorageManager.GetStorageDrive(); + await StorageManager.GetRootFolder(); + CurrentPath = StorageManager.StorageDrive.Root; + } + catch (Exception ex) + { + _notification.ShowError($"An error occurred while trying to initialize the storage manager.\n{ex.Message}"); + } + + InvalidateRelayCommands(); + } + } + + public void OnStorageItemDoubleClicked(StorageItem storageItem) + { + if (storageItem is StorageFolder && storageItem != null) + { + NavigateToPath(storageItem.Path); + } + else + { + DownloadStorageItem(storageItem as StorageFile); + } + } + + private void NavigateBack() + { + NavigateToPath(StorageManager.CurrentFolder.Parent); + } + + private void Refresh() + { + NavigateToPath(StorageManager.CurrentFolder.Path); + } + + private async void DownloadStorageItem(StorageFile storageFile) + { + var downloadsFolder = KnownFolders.GetPath(KnownFolder.Downloads); + var file = Path.Combine(downloadsFolder, storageFile.Name); + + FileStream fs = new FileStream(Path.Combine(downloadsFolder, storageFile.Name), FileMode.Create); + var handler = await StorageManager.DownloadFile(storageFile, fs); + handler.Completed += (_, __) => + { + fs.Dispose(); + }; + + handler.Canceled += (_, __) => + { + fs.Dispose(); + File.Delete(file); + }; + + handler.Failed += (_, __) => + { + fs.Dispose(); + File.Delete(file); + }; + + FileHandlers.Insert(0, new StorageFileHandlerModel(handler, file, StorageFileHandlerType.Download)); + } + + /// + /// Shows the file in explorer. + /// + /// Name of the file/folder. + public static void ShowInExplorer(String path) + { + Process.Start("explorer.exe", string.Format("/select,\"{0}\"", path)); + } + + private void RemoveFileHandler(StorageFileHandlerModel handler) + { + if (handler.Handler.Status == StorageFileHandlerStatus.Active) + { + if (_notification.ShowQuestion("Are you sure you want to cancel this file operation?")) + { + handler.Handler.Cancel(); + FileHandlers.Remove(handler); + } + } + else + { + FileHandlers.Remove(handler); } } } diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml index 46ef31c6b..a4a5c2946 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml @@ -11,22 +11,76 @@ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:local="clr-namespace:Tango.MachineStudio.Storage.Views" mc:Ignorable="d" - d:DesignHeight="1080" d:DesignWidth="1920" Background="Transparent" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}"> + d:DesignHeight="1080" x:Name="control" d:DesignWidth="1920" Background="Transparent" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}"> - + - + + + + - ACTIONS + ACTIONS - + + + + + + + + + + + + @@ -34,13 +88,16 @@ + + + - - @@ -55,21 +112,21 @@ Capacity: - + Free Space: - + - - + @@ -81,54 +138,185 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FILE TRANSFERS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml.cs index be7e82ca5..5da808b8c 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml.cs @@ -12,6 +12,8 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; +using Tango.Integration.Storage; +using Tango.MachineStudio.Storage.ViewModels; namespace Tango.MachineStudio.Storage.Views { @@ -20,9 +22,28 @@ namespace Tango.MachineStudio.Storage.Views /// public partial class MainView : UserControl { + private MainViewVM _vm; + public MainView() { InitializeComponent(); + Loaded += (_, __) => + { + _vm = DataContext as MainViewVM; + _vm.CurrentFolderChanged += _vm_CurrentFolderChanged; + }; + + } + + private void _vm_CurrentFolderChanged(object sender, EventArgs e) + { + ScrollViewer scrollViewer = gridStorageItems.FindChild(); + scrollViewer.ScrollToVerticalOffset(0); + } + + private void DataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e) + { + _vm.OnStorageItemDoubleClicked(gridStorageItems.SelectedItem as StorageItem); } } } diff --git a/Software/Visual_Studio/Tango.Core/IO/KnownFolders.cs b/Software/Visual_Studio/Tango.Core/IO/KnownFolders.cs new file mode 100644 index 000000000..841b0d8c4 --- /dev/null +++ b/Software/Visual_Studio/Tango.Core/IO/KnownFolders.cs @@ -0,0 +1,112 @@ +using System; +using System.Runtime.InteropServices; + +namespace Tango.Core.IO +{ + /// + /// Class containing methods to retrieve specific file system paths. + /// + public static class KnownFolders + { + private static string[] _knownFolderGuids = new string[] + { + "{56784854-C6CB-462B-8169-88E350ACB882}", // Contacts + "{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}", // Desktop + "{FDD39AD0-238F-46AF-ADB4-6C85480369C7}", // Documents + "{374DE290-123F-4565-9164-39C4925E467B}", // Downloads + "{1777F761-68AD-4D8A-87BD-30B759FA33DD}", // Favorites + "{BFB9D5E0-C6A9-404C-B2B2-AE6DB6AF4968}", // Links + "{4BD8D571-6D19-48D3-BE97-422220080E43}", // Music + "{33E28130-4E1E-4676-835A-98395C3BC3BB}", // Pictures + "{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}", // SavedGames + "{7D1D3A04-DEBB-4115-95CF-2F29DA2920DA}", // SavedSearches + "{18989B1D-99B5-455B-841C-AB7C74E4DDFC}", // Videos + }; + + /// + /// Gets the current path to the specified known folder as currently configured. This does + /// not require the folder to be existent. + /// + /// The known folder which current path will be returned. + /// The default path of the known folder. + /// Thrown if the path + /// could not be retrieved. + public static string GetPath(KnownFolder knownFolder) + { + return GetPath(knownFolder, false); + } + + /// + /// Gets the current path to the specified known folder as currently configured. This does + /// not require the folder to be existent. + /// + /// The known folder which current path will be returned. + /// Specifies if the paths of the default user (user profile + /// template) will be used. This requires administrative rights. + /// The default path of the known folder. + /// Thrown if the path + /// could not be retrieved. + public static string GetPath(KnownFolder knownFolder, bool defaultUser) + { + return GetPath(knownFolder, KnownFolderFlags.DontVerify, defaultUser); + } + + private static string GetPath(KnownFolder knownFolder, KnownFolderFlags flags, + bool defaultUser) + { + int result = SHGetKnownFolderPath(new Guid(_knownFolderGuids[(int)knownFolder]), + (uint)flags, new IntPtr(defaultUser ? -1 : 0), out IntPtr outPath); + if (result >= 0) + { + string path = Marshal.PtrToStringUni(outPath); + Marshal.FreeCoTaskMem(outPath); + return path; + } + else + { + throw new ExternalException("Unable to retrieve the known folder path. It may not " + + "be available on this system.", result); + } + } + + [DllImport("Shell32.dll")] + private static extern int SHGetKnownFolderPath( + [MarshalAs(UnmanagedType.LPStruct)]Guid rfid, uint dwFlags, IntPtr hToken, + out IntPtr ppszPath); + + [Flags] + private enum KnownFolderFlags : uint + { + SimpleIDList = 0x00000100, + NotParentRelative = 0x00000200, + DefaultPath = 0x00000400, + Init = 0x00000800, + NoAlias = 0x00001000, + DontUnexpand = 0x00002000, + DontVerify = 0x00004000, + Create = 0x00008000, + NoAppcontainerRedirection = 0x00010000, + AliasOnly = 0x80000000 + } + } + + /// + /// Standard folders registered with the system. These folders are installed with Windows Vista + /// and later operating systems, and a computer will have only folders appropriate to it + /// installed. + /// + public enum KnownFolder + { + Contacts, + Desktop, + Documents, + Downloads, + Favorites, + Links, + Music, + Pictures, + SavedGames, + SavedSearches, + Videos + } +} diff --git a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj index ca9a0a82f..16451aa4e 100644 --- a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj +++ b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj @@ -85,6 +85,7 @@ GlobalVersionInfo.cs + @@ -190,7 +191,7 @@ - + diff --git a/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs b/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs index ae7e648f9..72e507a40 100644 --- a/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs +++ b/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs @@ -317,6 +317,12 @@ namespace Tango.Emulations.Emulators case MessageType.GetFilesRequest: HandleGetFilesRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; + case MessageType.FileDownloadRequest: + HandleFileDownloadRequest(MessageFactory.ParseTangoMessageFromContainer(container)); + break; + case MessageType.FileChunkDownloadRequest: + HandleFileChunkDownloadRequest(MessageFactory.ParseTangoMessageFromContainer(container)); + break; } } @@ -967,50 +973,100 @@ namespace Tango.Emulations.Emulators private void HandleGetStorageInfoRequest(TangoMessage request) { + var d = new DriveInfo("C"); + Transporter.SendResponse(new GetStorageInfoResponse() { - Capacity = 1024, - FreeSpace = 500, + Capacity = d.TotalSize, + FreeSpace = d.TotalFreeSpace, Root = "C:\\" }, request.Container.Token); } private void HandleGetFilesRequest(TangoMessage request) { - String path = request.Message.Path; - GetFilesResponse response = new GetFilesResponse(); - foreach (var dir in Directory.GetDirectories(path)) + bool failed = false; + String msg = null; + + try { - DirectoryInfo dirInfo = new DirectoryInfo(dir); + String path = request.Message.Path; - response.Items.Add(new PMR.IO.FileInfo() + foreach (var dir in Directory.GetDirectories(path)) { - Attribute = FileAttribute.Directory, - FullPath = dir, - LastModifiedDate = dirInfo.LastWriteTime.DayOfYear, - LastModifiedTime = dirInfo.LastWriteTime.Hour, - Name = Path.GetFileName(dir), - }); + DirectoryInfo dirInfo = new DirectoryInfo(dir); + + response.Items.Add(new PMR.IO.FileInfo() + { + Attribute = FileAttribute.Directory, + FullPath = dir, + LastModifiedDate = dirInfo.LastWriteTime.DayOfYear, + LastModifiedTime = dirInfo.LastWriteTime.Hour, + Name = Path.GetFileName(dir), + }); + } + + foreach (var file in Directory.GetFiles(path)) + { + System.IO.FileInfo fileInfo = new System.IO.FileInfo(file); + + response.Items.Add(new PMR.IO.FileInfo() + { + Attribute = FileAttribute.Unspecified, + FullPath = file, + LastModifiedDate = fileInfo.LastWriteTime.DayOfYear, + LastModifiedTime = fileInfo.LastWriteTime.Hour, + Name = Path.GetFileName(file), + Length = (int)fileInfo.Length, + }); + } + } + catch (Exception ex) + { + failed = true; + msg = ex.Message; } - foreach (var file in Directory.GetFiles(path)) + Transporter.SendResponse(response, request.Container.Token, false, failed ? ErrorCode.GeneralError : ErrorCode.None, msg); + } + + private void HandleFileDownloadRequest(TangoMessage request) + { + long length = File.Exists(request.Message.FileName) ? new System.IO.FileInfo(request.Message.FileName).Length : 0; + + Transporter.SendResponse(new FileDownloadResponse() { - System.IO.FileInfo fileInfo = new System.IO.FileInfo(file); + DownloadID = Guid.NewGuid().ToString(), + MaxChunkLength = Math.Min(1024, length), + }, request.Container.Token, null, File.Exists(request.Message.FileName) ? ErrorCode.None : ErrorCode.FileNotFound); + } + + private void HandleFileChunkDownloadRequest(TangoMessage request) + { + var message = request.Message; - response.Items.Add(new PMR.IO.FileInfo() + try + { + using (FileStream fs = new FileStream(message.FileName, FileMode.Open)) { - Attribute = FileAttribute.Unspecified, - FullPath = file, - LastModifiedDate = fileInfo.LastWriteTime.DayOfYear, - LastModifiedTime = fileInfo.LastWriteTime.Hour, - Name = Path.GetFileName(file), - Length = (int)fileInfo.Length, - }); + fs.Position = message.Position; + byte[] buffer = new byte[Math.Min(1024, fs.Length - fs.Position)]; + fs.Read(buffer, 0, buffer.Length); + Transporter.SendResponse(new FileChunkDownloadResponse() + { + Buffer = ByteString.CopyFrom(buffer), + }, request.Container.Token); + } + } + catch (Exception ex) + { + Transporter.SendResponse(new FileChunkDownloadResponse() + { + + }, request.Container.Token, null, ErrorCode.FileRequestDenied, ex.Message); } - - Transporter.SendResponse(response, request.Container.Token); } #endregion diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageDrive.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageDrive.cs index c313ac0cb..28f390bc9 100644 --- a/Software/Visual_Studio/Tango.Integration/Storage/StorageDrive.cs +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageDrive.cs @@ -9,8 +9,8 @@ namespace Tango.Integration.Storage { public class StorageDrive : ExtendedObject { - public int Capacity { get; set; } - public int FreeSpace { get; set; } + public long Capacity { get; set; } + public long FreeSpace { get; set; } public String Root { get; set; } } } diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageFile.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageFile.cs index 069b1743d..06c966649 100644 --- a/Software/Visual_Studio/Tango.Integration/Storage/StorageFile.cs +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageFile.cs @@ -9,6 +9,6 @@ namespace Tango.Integration.Storage { public class StorageFile : StorageItem { - public int Length { get; set; } + public long Length { get; set; } } } diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandler.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandler.cs index 72a4b2c87..6a9c5cae4 100644 --- a/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandler.cs +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandler.cs @@ -21,9 +21,19 @@ namespace Tango.Integration.Storage } - internal StorageFileHandler(Action cancelAction) + internal StorageFileHandler(StorageFile storageFile, Action cancelAction) { _cancelAction = cancelAction; + StorageFile = storageFile; + } + + public StorageFile StorageFile { get; set; } + + private StorageFileHandlerStatus _status; + public StorageFileHandlerStatus Status + { + get { return _status; } + private set { _status = value; RaisePropertyChangedAuto(); } } private long _current; @@ -38,6 +48,11 @@ namespace Tango.Integration.Storage Current = _current, Total = _total, }); + + if (Status != StorageFileHandlerStatus.Active) + { + Status = StorageFileHandlerStatus.Active; + } } } @@ -53,21 +68,25 @@ namespace Tango.Integration.Storage return Task.Factory.StartNew(() => { _cancelAction.Invoke(); - }); + Status = StorageFileHandlerStatus.Canceled; + }); } internal void RaiseCompleted() { + Status = StorageFileHandlerStatus.Completed; Completed?.Invoke(this, new EventArgs()); } internal void RaiseCanceled() { + Status = StorageFileHandlerStatus.Canceled; Canceled?.Invoke(this, new EventArgs()); } internal void RaiseFailed(Exception ex) { + Status = StorageFileHandlerStatus.Failed; Failed?.Invoke(this, ex); } } diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandlerStatus.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandlerStatus.cs new file mode 100644 index 000000000..7fb30dd16 --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandlerStatus.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Integration.Storage +{ + public enum StorageFileHandlerStatus + { + Pending, + Active, + Canceled, + Failed, + Completed, + } +} diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageItem.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageItem.cs index e8a725277..3881dd528 100644 --- a/Software/Visual_Studio/Tango.Integration/Storage/StorageItem.cs +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageItem.cs @@ -26,8 +26,21 @@ namespace Tango.Integration.Storage { get { + String root = System.IO.Path.GetPathRoot(Path); var parent = Directory.GetParent(Path); - return parent.FullName.Replace(parent.Root.FullName, "/").Replace("\\", "/"); + + if (root == "\\") + { + return parent.FullName.Replace(parent.Root.FullName, "/").Replace("\\", "/"); + } + else if (parent != null) + { + return parent.FullName; + } + else + { + return null; + } } } diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs index bb880f1bd..d640ba0c6 100644 --- a/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs @@ -213,10 +213,14 @@ namespace Tango.Integration.Storage long max_length = fileUploadResponse.Message.MaxChunkLength; bool canceled = false; - StorageFileHandler handler = new StorageFileHandler(() => + StorageFileHandler handler = new StorageFileHandler(new StorageFile() { - canceled = true; - }); + Path = path, + Length = (int)stream.Length, + }, () => + { + canceled = true; + }); handler.Total = stream.Length; @@ -284,10 +288,10 @@ namespace Tango.Integration.Storage long max_length = fileDownloadResponse.Message.MaxChunkLength; bool canceled = false; - StorageFileHandler handler = new StorageFileHandler(() => - { - canceled = true; - }); + StorageFileHandler handler = new StorageFileHandler(file, () => + { + canceled = true; + }); handler.Total = file.Length; @@ -320,11 +324,6 @@ namespace Tango.Integration.Storage } else { - var a = _transporter.SendRequest(new FileChunkDownloadRequest() - { - IsCanceled = true, - }).Result; - handler.RaiseCanceled(); return; } diff --git a/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj b/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj index d96191191..8498219bc 100644 --- a/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj +++ b/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj @@ -106,6 +106,7 @@ + diff --git a/Software/Visual_Studio/Tango.PMR/Common/MessageType.cs b/Software/Visual_Studio/Tango.PMR/Common/MessageType.cs index 4e8b7f73c..fea3f95a9 100644 --- a/Software/Visual_Studio/Tango.PMR/Common/MessageType.cs +++ b/Software/Visual_Studio/Tango.PMR/Common/MessageType.cs @@ -22,7 +22,7 @@ namespace Tango.PMR.Common { static MessageTypeReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "ChFNZXNzYWdlVHlwZS5wcm90bxIQVGFuZ28uUE1SLkNvbW1vbiqsKwoLTWVz", + "ChFNZXNzYWdlVHlwZS5wcm90bxIQVGFuZ28uUE1SLkNvbW1vbiqWLQoLTWVz", "c2FnZVR5cGUSCAoETm9uZRAAEhEKDUVycm9yUmVzcG9uc2UQARIUChBDYWxj", "dWxhdGVSZXF1ZXN0EAMSFQoRQ2FsY3VsYXRlUmVzcG9uc2UQBBITCg9Qcm9n", "cmVzc1JlcXVlc3QQBRIUChBQcm9ncmVzc1Jlc3BvbnNlEAYSHAoYU3R1YkNh", @@ -146,8 +146,13 @@ namespace Tango.PMR.Common { "EhIKDURlbGV0ZVJlcXVlc3QQ4jYSEwoORGVsZXRlUmVzcG9uc2UQ4zYSGgoV", "R2V0U3RvcmFnZUluZm9SZXF1ZXN0EOQ2EhsKFkdldFN0b3JhZ2VJbmZvUmVz", "cG9uc2UQ5TYSFAoPR2V0RmlsZXNSZXF1ZXN0EOY2EhUKEEdldEZpbGVzUmVz", - "cG9uc2UQ5zZCHAoaY29tLnR3aW5lLnRhbmdvLnBtci5jb21tb25iBnByb3Rv", - "Mw==")); + "cG9uc2UQ5zYSGAoTRmlsZURvd25sb2FkUmVxdWVzdBDoNhIZChRGaWxlRG93", + "bmxvYWRSZXNwb25zZRDpNhIdChhGaWxlQ2h1bmtEb3dubG9hZFJlcXVlc3QQ", + "6jYSHgoZRmlsZUNodW5rRG93bmxvYWRSZXNwb25zZRDrNhIbChZWYWxpZGF0", + "ZVZlcnNpb25SZXF1ZXN0EOw2EhwKF1ZhbGlkYXRlVmVyc2lvblJlc3BvbnNl", + "EO02EhsKFkFjdGl2YXRlVmVyc2lvblJlcXVlc3QQ7jYSHAoXQWN0aXZhdGVW", + "ZXJzaW9uUmVzcG9uc2UQ7zZCHAoaY29tLnR3aW5lLnRhbmdvLnBtci5jb21t", + "b25iBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Tango.PMR.Common.MessageType), }, null)); @@ -383,6 +388,14 @@ namespace Tango.PMR.Common { [pbr::OriginalName("GetStorageInfoResponse")] GetStorageInfoResponse = 7013, [pbr::OriginalName("GetFilesRequest")] GetFilesRequest = 7014, [pbr::OriginalName("GetFilesResponse")] GetFilesResponse = 7015, + [pbr::OriginalName("FileDownloadRequest")] FileDownloadRequest = 7016, + [pbr::OriginalName("FileDownloadResponse")] FileDownloadResponse = 7017, + [pbr::OriginalName("FileChunkDownloadRequest")] FileChunkDownloadRequest = 7018, + [pbr::OriginalName("FileChunkDownloadResponse")] FileChunkDownloadResponse = 7019, + [pbr::OriginalName("ValidateVersionRequest")] ValidateVersionRequest = 7020, + [pbr::OriginalName("ValidateVersionResponse")] ValidateVersionResponse = 7021, + [pbr::OriginalName("ActivateVersionRequest")] ActivateVersionRequest = 7022, + [pbr::OriginalName("ActivateVersionResponse")] ActivateVersionResponse = 7023, } #endregion diff --git a/Software/Visual_Studio/Tango.PMR/IO/FileChunkDownloadRequest.cs b/Software/Visual_Studio/Tango.PMR/IO/FileChunkDownloadRequest.cs index 0c68646da..ff0a32ba8 100644 --- a/Software/Visual_Studio/Tango.PMR/IO/FileChunkDownloadRequest.cs +++ b/Software/Visual_Studio/Tango.PMR/IO/FileChunkDownloadRequest.cs @@ -23,14 +23,13 @@ namespace Tango.PMR.IO { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "Ch5GaWxlQ2h1bmtEb3dubG9hZFJlcXVlc3QucHJvdG8SDFRhbmdvLlBNUi5J", - "TyJmChhGaWxlQ2h1bmtEb3dubG9hZFJlcXVlc3QSEgoKRG93bmxvYWRJRBgB", - "IAEoCRIQCghGaWxlTmFtZRgCIAEoCRIQCghQb3NpdGlvbhgDIAEoAxISCgpJ", - "c0NhbmNlbGVkGAQgASgIQhgKFmNvbS50d2luZS50YW5nby5wbXIuaW9iBnBy", - "b3RvMw==")); + "TyJSChhGaWxlQ2h1bmtEb3dubG9hZFJlcXVlc3QSEgoKRG93bmxvYWRJRBgB", + "IAEoCRIQCghGaWxlTmFtZRgCIAEoCRIQCghQb3NpdGlvbhgDIAEoA0IYChZj", + "b20udHdpbmUudGFuZ28ucG1yLmlvYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.IO.FileChunkDownloadRequest), global::Tango.PMR.IO.FileChunkDownloadRequest.Parser, new[]{ "DownloadID", "FileName", "Position", "IsCanceled" }, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.IO.FileChunkDownloadRequest), global::Tango.PMR.IO.FileChunkDownloadRequest.Parser, new[]{ "DownloadID", "FileName", "Position" }, null, null, null) })); } #endregion @@ -64,7 +63,6 @@ namespace Tango.PMR.IO { downloadID_ = other.downloadID_; fileName_ = other.fileName_; position_ = other.position_; - isCanceled_ = other.isCanceled_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -105,17 +103,6 @@ namespace Tango.PMR.IO { } } - /// Field number for the "IsCanceled" field. - public const int IsCanceledFieldNumber = 4; - private bool isCanceled_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool IsCanceled { - get { return isCanceled_; } - set { - isCanceled_ = value; - } - } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as FileChunkDownloadRequest); @@ -132,7 +119,6 @@ namespace Tango.PMR.IO { if (DownloadID != other.DownloadID) return false; if (FileName != other.FileName) return false; if (Position != other.Position) return false; - if (IsCanceled != other.IsCanceled) return false; return true; } @@ -142,7 +128,6 @@ namespace Tango.PMR.IO { if (DownloadID.Length != 0) hash ^= DownloadID.GetHashCode(); if (FileName.Length != 0) hash ^= FileName.GetHashCode(); if (Position != 0L) hash ^= Position.GetHashCode(); - if (IsCanceled != false) hash ^= IsCanceled.GetHashCode(); return hash; } @@ -165,10 +150,6 @@ namespace Tango.PMR.IO { output.WriteRawTag(24); output.WriteInt64(Position); } - if (IsCanceled != false) { - output.WriteRawTag(32); - output.WriteBool(IsCanceled); - } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -183,9 +164,6 @@ namespace Tango.PMR.IO { if (Position != 0L) { size += 1 + pb::CodedOutputStream.ComputeInt64Size(Position); } - if (IsCanceled != false) { - size += 1 + 1; - } return size; } @@ -203,9 +181,6 @@ namespace Tango.PMR.IO { if (other.Position != 0L) { Position = other.Position; } - if (other.IsCanceled != false) { - IsCanceled = other.IsCanceled; - } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -228,10 +203,6 @@ namespace Tango.PMR.IO { Position = input.ReadInt64(); break; } - case 32: { - IsCanceled = input.ReadBool(); - break; - } } } } diff --git a/Software/Visual_Studio/Tango.PMR/IO/FileInfo.cs b/Software/Visual_Studio/Tango.PMR/IO/FileInfo.cs index d6c1b7fbd..4728be2c1 100644 --- a/Software/Visual_Studio/Tango.PMR/IO/FileInfo.cs +++ b/Software/Visual_Studio/Tango.PMR/IO/FileInfo.cs @@ -24,7 +24,7 @@ namespace Tango.PMR.IO { string.Concat( "Cg5GaWxlSW5mby5wcm90bxIMVGFuZ28uUE1SLklPGhNGaWxlQXR0cmlidXRl", "LnByb3RvIp4BCghGaWxlSW5mbxIMCgROYW1lGAEgASgJEhAKCEZ1bGxQYXRo", - "GAIgASgJEg4KBkxlbmd0aBgDIAEoBRIYChBMYXN0TW9kaWZpZWREYXRlGAQg", + "GAIgASgJEg4KBkxlbmd0aBgDIAEoAxIYChBMYXN0TW9kaWZpZWREYXRlGAQg", "ASgFEhgKEExhc3RNb2RpZmllZFRpbWUYBSABKAUSLgoJQXR0cmlidXRlGAYg", "ASgOMhsuVGFuZ28uUE1SLklPLkZpbGVBdHRyaWJ1dGVCGAoWY29tLnR3aW5l", "LnRhbmdvLnBtci5pb2IGcHJvdG8z")); @@ -99,9 +99,9 @@ namespace Tango.PMR.IO { /// Field number for the "Length" field. public const int LengthFieldNumber = 3; - private int length_; + private long length_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Length { + public long Length { get { return length_; } set { length_ = value; @@ -168,7 +168,7 @@ namespace Tango.PMR.IO { int hash = 1; if (Name.Length != 0) hash ^= Name.GetHashCode(); if (FullPath.Length != 0) hash ^= FullPath.GetHashCode(); - if (Length != 0) hash ^= Length.GetHashCode(); + if (Length != 0L) hash ^= Length.GetHashCode(); if (LastModifiedDate != 0) hash ^= LastModifiedDate.GetHashCode(); if (LastModifiedTime != 0) hash ^= LastModifiedTime.GetHashCode(); if (Attribute != 0) hash ^= Attribute.GetHashCode(); @@ -190,9 +190,9 @@ namespace Tango.PMR.IO { output.WriteRawTag(18); output.WriteString(FullPath); } - if (Length != 0) { + if (Length != 0L) { output.WriteRawTag(24); - output.WriteInt32(Length); + output.WriteInt64(Length); } if (LastModifiedDate != 0) { output.WriteRawTag(32); @@ -217,8 +217,8 @@ namespace Tango.PMR.IO { if (FullPath.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(FullPath); } - if (Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Length); + if (Length != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Length); } if (LastModifiedDate != 0) { size += 1 + pb::CodedOutputStream.ComputeInt32Size(LastModifiedDate); @@ -243,7 +243,7 @@ namespace Tango.PMR.IO { if (other.FullPath.Length != 0) { FullPath = other.FullPath; } - if (other.Length != 0) { + if (other.Length != 0L) { Length = other.Length; } if (other.LastModifiedDate != 0) { @@ -274,7 +274,7 @@ namespace Tango.PMR.IO { break; } case 24: { - Length = input.ReadInt32(); + Length = input.ReadInt64(); break; } case 32: { diff --git a/Software/Visual_Studio/Tango.PMR/IO/GetStorageInfoResponse.cs b/Software/Visual_Studio/Tango.PMR/IO/GetStorageInfoResponse.cs index 86f6a900b..66526e5c2 100644 --- a/Software/Visual_Studio/Tango.PMR/IO/GetStorageInfoResponse.cs +++ b/Software/Visual_Studio/Tango.PMR/IO/GetStorageInfoResponse.cs @@ -23,8 +23,8 @@ namespace Tango.PMR.IO { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChxHZXRTdG9yYWdlSW5mb1Jlc3BvbnNlLnByb3RvEgxUYW5nby5QTVIuSU8i", - "SwoWR2V0U3RvcmFnZUluZm9SZXNwb25zZRIQCghDYXBhY2l0eRgBIAEoBRIR", - "CglGcmVlU3BhY2UYAiABKAUSDAoEUm9vdBgDIAEoCUIYChZjb20udHdpbmUu", + "SwoWR2V0U3RvcmFnZUluZm9SZXNwb25zZRIQCghDYXBhY2l0eRgBIAEoAxIR", + "CglGcmVlU3BhY2UYAiABKAMSDAoEUm9vdBgDIAEoCUIYChZjb20udHdpbmUu", "dGFuZ28ucG1yLmlvYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, @@ -72,9 +72,9 @@ namespace Tango.PMR.IO { /// Field number for the "Capacity" field. public const int CapacityFieldNumber = 1; - private int capacity_; + private long capacity_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int Capacity { + public long Capacity { get { return capacity_; } set { capacity_ = value; @@ -83,9 +83,9 @@ namespace Tango.PMR.IO { /// Field number for the "FreeSpace" field. public const int FreeSpaceFieldNumber = 2; - private int freeSpace_; + private long freeSpace_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int FreeSpace { + public long FreeSpace { get { return freeSpace_; } set { freeSpace_ = value; @@ -125,8 +125,8 @@ namespace Tango.PMR.IO { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - if (Capacity != 0) hash ^= Capacity.GetHashCode(); - if (FreeSpace != 0) hash ^= FreeSpace.GetHashCode(); + if (Capacity != 0L) hash ^= Capacity.GetHashCode(); + if (FreeSpace != 0L) hash ^= FreeSpace.GetHashCode(); if (Root.Length != 0) hash ^= Root.GetHashCode(); return hash; } @@ -138,13 +138,13 @@ namespace Tango.PMR.IO { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - if (Capacity != 0) { + if (Capacity != 0L) { output.WriteRawTag(8); - output.WriteInt32(Capacity); + output.WriteInt64(Capacity); } - if (FreeSpace != 0) { + if (FreeSpace != 0L) { output.WriteRawTag(16); - output.WriteInt32(FreeSpace); + output.WriteInt64(FreeSpace); } if (Root.Length != 0) { output.WriteRawTag(26); @@ -155,11 +155,11 @@ namespace Tango.PMR.IO { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - if (Capacity != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(Capacity); + if (Capacity != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Capacity); } - if (FreeSpace != 0) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(FreeSpace); + if (FreeSpace != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(FreeSpace); } if (Root.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(Root); @@ -172,10 +172,10 @@ namespace Tango.PMR.IO { if (other == null) { return; } - if (other.Capacity != 0) { + if (other.Capacity != 0L) { Capacity = other.Capacity; } - if (other.FreeSpace != 0) { + if (other.FreeSpace != 0L) { FreeSpace = other.FreeSpace; } if (other.Root.Length != 0) { @@ -192,11 +192,11 @@ namespace Tango.PMR.IO { input.SkipLastField(); break; case 8: { - Capacity = input.ReadInt32(); + Capacity = input.ReadInt64(); break; } case 16: { - FreeSpace = input.ReadInt32(); + FreeSpace = input.ReadInt64(); break; } case 26: { -- cgit v1.3.1 From 1e2ae1c1973fd5661815f18c93ee1171a5c08da5 Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Thu, 29 Nov 2018 14:26:54 +0200 Subject: Working on machine studio storage module. --- Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 20578304 -> 20578304 bytes Software/PMR/Messages/IO/DeleteRequest.proto | 5 +- .../PMR/Messages/IO/FileChunkUploadRequest.proto | 3 +- Software/PMR/Messages/IO/FileUploadRequest.proto | 2 +- .../ViewModels/MainViewVM.cs | 152 +++++++++++++++++++-- .../Views/MainView.xaml | 16 ++- .../Tango.Emulations/Emulators/MachineEmulator.cs | 78 ++++++++++- .../Tango.Integration/Storage/StorageManager.cs | 13 +- .../Visual_Studio/Tango.PMR/IO/DeleteRequest.cs | 45 ++++-- .../Tango.PMR/IO/FileChunkUploadRequest.cs | 40 +++++- .../Tango.PMR/IO/FileUploadRequest.cs | 40 +++--- .../Tango.UnitTesting/RemoteRunner_TST.cs | 2 +- .../Tango.RemoteRunner.UI/MainWindowVM.cs | 6 +- .../Tango.BuildExtensions/RemoteDebugCommand.cs | 2 +- 15 files changed, 342 insertions(+), 62 deletions(-) (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels') diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index 243267834..31fca8645 100644 Binary files a/Software/DB/Tango.mdf and b/Software/DB/Tango.mdf differ diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf index fc2dfed0f..dbb972b80 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/PMR/Messages/IO/DeleteRequest.proto b/Software/PMR/Messages/IO/DeleteRequest.proto index c385910f1..584cdf1ea 100644 --- a/Software/PMR/Messages/IO/DeleteRequest.proto +++ b/Software/PMR/Messages/IO/DeleteRequest.proto @@ -1,9 +1,12 @@ syntax = "proto3"; +import "FileAttribute.proto"; + package Tango.PMR.IO; option java_package = "com.twine.tango.pmr.io"; message DeleteRequest { - string Path = 2; + string Path = 1; + FileAttribute Attribute = 2; } \ No newline at end of file diff --git a/Software/PMR/Messages/IO/FileChunkUploadRequest.proto b/Software/PMR/Messages/IO/FileChunkUploadRequest.proto index 1bebb0f9d..fed5b1d2b 100644 --- a/Software/PMR/Messages/IO/FileChunkUploadRequest.proto +++ b/Software/PMR/Messages/IO/FileChunkUploadRequest.proto @@ -6,6 +6,7 @@ option java_package = "com.twine.tango.pmr.io"; message FileChunkUploadRequest { string UploadID = 1; - bytes Buffer = 2; + string Path = 2; + bytes Buffer = 3; bool IsCanceled = 4; } \ No newline at end of file diff --git a/Software/PMR/Messages/IO/FileUploadRequest.proto b/Software/PMR/Messages/IO/FileUploadRequest.proto index 7c6b744f6..cace8ab47 100644 --- a/Software/PMR/Messages/IO/FileUploadRequest.proto +++ b/Software/PMR/Messages/IO/FileUploadRequest.proto @@ -5,6 +5,6 @@ option java_package = "com.twine.tango.pmr.io"; message FileUploadRequest { - string FileName = 1; + string Path = 1; int64 Length = 2; } \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs index 1c6371f43..12bb8242a 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.Win32; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; @@ -36,7 +37,7 @@ namespace Tango.MachineStudio.Storage.ViewModels public StorageItem SelectedStorageItem { get { return _selectedStorageItem; } - set { _selectedStorageItem = value; RaisePropertyChangedAuto(); } + set { _selectedStorageItem = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } } private String _currentPath; @@ -46,6 +47,8 @@ namespace Tango.MachineStudio.Storage.ViewModels set { _currentPath = value; RaisePropertyChangedAuto(); } } + public ObservableCollection FileHandlers { get; set; } + public RelayCommand BackCommand { get; set; } public RelayCommand RefreshCommand { get; set; } @@ -58,7 +61,15 @@ namespace Tango.MachineStudio.Storage.ViewModels public RelayCommand RemoveFileHandlerCommand { get; set; } - public ObservableCollection FileHandlers { get; set; } + public RelayCommand DownloadFileCommand { get; set; } + + public RelayCommand DeleteFileCommand { get; set; } + + public RelayCommand CreateFolderCommand { get; set; } + + public RelayCommand DeleteFolderCommand { get; set; } + + public RelayCommand UploadFileCommand { get; set; } public MainViewVM(IStudioApplicationManager applicationManager, INotificationProvider notificationProvider) { @@ -74,6 +85,89 @@ namespace Tango.MachineStudio.Storage.ViewModels OpenFileHandlerCommand = new RelayCommand(OpenFileHandler); RefreshCommand = new RelayCommand(Refresh, () => StorageManager != null); RemoveFileHandlerCommand = new RelayCommand(RemoveFileHandler); + DownloadFileCommand = new RelayCommand(DownloadFile, () => StorageManager != null && SelectedStorageItem != null && SelectedStorageItem is StorageFile); + DeleteFileCommand = new RelayCommand(DeleteFile, () => StorageManager != null && SelectedStorageItem != null && SelectedStorageItem is StorageFile); + CreateFolderCommand = new RelayCommand(CreateFolder, () => StorageManager != null && StorageManager.CurrentFolder != null); + DeleteFolderCommand = new RelayCommand(DeleteFolder, () => StorageManager != null && SelectedStorageItem != null && SelectedStorageItem is StorageFolder); + UploadFileCommand = new RelayCommand(UploadFile, () => StorageManager != null && StorageManager.CurrentFolder != null); + } + + private void UploadFile() + { + OpenFileDialog dlg = new OpenFileDialog(); + dlg.Title = "Selected a file to upload"; + if (dlg.ShowDialog().Value) + { + UploadFile(dlg.FileName); + } + } + + private async void DeleteFolder() + { + if (SelectedStorageItem == null) return; + + if (_notification.ShowQuestion("Are you sure you want to delete the selected folder?")) + { + try + { + IsFree = false; + await StorageManager.DeleteItem(SelectedStorageItem); + Refresh(); + } + catch (Exception ex) + { + _notification.ShowError($"Error deleting the selected folder.\n{ex.Message}"); + } + + IsFree = true; + } + } + + private async void CreateFolder() + { + try + { + var name = _notification.ShowTextInput("Enter Folder Name", ""); + + if (!String.IsNullOrWhiteSpace(name)) + { + IsFree = false; + await StorageManager.CreateFolder(Path.Combine(StorageManager.CurrentPath, name)); + Refresh(); + } + } + catch (Exception ex) + { + _notification.ShowError($"Error creating the new folder.\n{ex.Message}"); + } + + IsFree = true; + } + + private async void DeleteFile() + { + if (SelectedStorageItem == null) return; + + if (_notification.ShowQuestion("Are you sure you want to delete the selected file?")) + { + try + { + IsFree = false; + await StorageManager.DeleteItem(SelectedStorageItem); + Refresh(); + } + catch (Exception ex) + { + _notification.ShowError($"Error deleting the selected file.\n{ex.Message}"); + } + + IsFree = true; + } + } + + private void DownloadFile() + { + DownloadStorageItem(SelectedStorageItem as StorageFile); } private void OpenFileHandler(StorageFileHandlerModel handler) @@ -112,7 +206,7 @@ namespace Tango.MachineStudio.Storage.ViewModels } } - private async void NavigateToPath(String path) + private async void NavigateToPath(String path, bool raiseEvent = true) { IsFree = false; @@ -120,7 +214,11 @@ namespace Tango.MachineStudio.Storage.ViewModels { await StorageManager.GetFolder(path); CurrentPath = StorageManager.CurrentPath; - CurrentFolderChanged?.Invoke(this, new EventArgs()); + + if (raiseEvent) + { + CurrentFolderChanged?.Invoke(this, new EventArgs()); + } } catch (Exception ex) { @@ -171,16 +269,44 @@ namespace Tango.MachineStudio.Storage.ViewModels private void Refresh() { - NavigateToPath(StorageManager.CurrentFolder.Path); + NavigateToPath(StorageManager.CurrentFolder.Path, false); } private async void DownloadStorageItem(StorageFile storageFile) { - var downloadsFolder = KnownFolders.GetPath(KnownFolder.Downloads); - var file = Path.Combine(downloadsFolder, storageFile.Name); + SaveFileDialog dlg = new SaveFileDialog(); + dlg.Title = "Select download location"; + dlg.DefaultExt = Path.GetExtension(storageFile.Path); + dlg.FileName = storageFile.Name; + if (dlg.ShowDialog().Value) + { + FileStream fs = new FileStream(dlg.FileName, FileMode.Create); + var handler = await StorageManager.DownloadFile(storageFile, fs); + handler.Completed += (_, __) => + { + fs.Dispose(); + }; - FileStream fs = new FileStream(Path.Combine(downloadsFolder, storageFile.Name), FileMode.Create); - var handler = await StorageManager.DownloadFile(storageFile, fs); + handler.Canceled += (_, __) => + { + fs.Dispose(); + File.Delete(dlg.FileName); + }; + + handler.Failed += (_, __) => + { + fs.Dispose(); + File.Delete(dlg.FileName); + }; + + FileHandlers.Insert(0, new StorageFileHandlerModel(handler, dlg.FileName, StorageFileHandlerType.Download)); + } + } + + private async void UploadFile(String path) + { + FileStream fs = new FileStream(path, FileMode.Open); + var handler = await StorageManager.UploadFile(Path.Combine(StorageManager.CurrentPath, Path.GetFileName(path)), fs); handler.Completed += (_, __) => { fs.Dispose(); @@ -189,16 +315,16 @@ namespace Tango.MachineStudio.Storage.ViewModels handler.Canceled += (_, __) => { fs.Dispose(); - File.Delete(file); + File.Delete(path); }; handler.Failed += (_, __) => { fs.Dispose(); - File.Delete(file); + File.Delete(path); }; - FileHandlers.Insert(0, new StorageFileHandlerModel(handler, file, StorageFileHandlerType.Download)); + FileHandlers.Insert(0, new StorageFileHandlerModel(handler, path, StorageFileHandlerType.Upload)); } /// diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml index a4a5c2946..311d18f54 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml @@ -29,27 +29,33 @@ ACTIONS - + - - - - - + + + + + + + + + + + + + Upgrading Machine Firmware + + + + + + + + + Firmware Upgrade Completed + + + + + + + + + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/FirmwareUpgradeView.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/FirmwareUpgradeView.xaml.cs new file mode 100644 index 000000000..17220e615 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/FirmwareUpgradeView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +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.Navigation; +using System.Windows.Shapes; + +namespace Tango.MachineStudio.UI.Views +{ + /// + /// Interaction logic for FirmwareUpgradeView.xaml + /// + public partial class FirmwareUpgradeView : UserControl + { + public FirmwareUpgradeView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Events/app.config b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Events/app.config index 1e22e6a88..e67f6e7f8 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Events/app.config +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Events/app.config @@ -1,61 +1,65 @@ - + -
+
- - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + - + - + - + diff --git a/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs b/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs index 0decf4c9c..4a0758a4c 100644 --- a/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs +++ b/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs @@ -335,6 +335,12 @@ namespace Tango.Emulations.Emulators case MessageType.FileChunkUploadRequest: HandleFileChunkUploadRequest(MessageFactory.ParseTangoMessageFromContainer(container)); break; + case MessageType.ValidateVersionRequest: + HandleValidateVersionRequest(MessageFactory.ParseTangoMessageFromContainer(container)); + break; + case MessageType.ActivateVersionRequest: + HandleActivateVersionRequest(MessageFactory.ParseTangoMessageFromContainer(container)); + break; } } @@ -1145,6 +1151,24 @@ namespace Tango.Emulations.Emulators } } + private void HandleValidateVersionRequest(TangoMessage request) + { + Task.Factory.StartNew(() => + { + Thread.Sleep(3000); + Transporter.SendResponse(new ValidateVersionResponse(), request.Container.Token); + }); + } + + private void HandleActivateVersionRequest(TangoMessage request) + { + Task.Factory.StartNew(() => + { + Thread.Sleep(3000); + Transporter.SendResponse(new ActivateVersionResponse(), request.Container.Token); + }); + } + #endregion #region Public Methods diff --git a/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeHandler.cs b/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeHandler.cs new file mode 100644 index 000000000..f944a2587 --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeHandler.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Integration.Storage; + +namespace Tango.Integration.Operation +{ + public class FirmwareUpgradeHandler : ExtendedObject + { + private Action _cancelAction; + + public event EventHandler Progress; + public event EventHandler Completed; + public event EventHandler Canceled; + public event EventHandler Failed; + + internal FirmwareUpgradeHandler() + { + + } + + internal FirmwareUpgradeHandler(Action cancelAction) + { + _cancelAction = cancelAction; + } + + private FirmwareUpgradeStatus _status; + public FirmwareUpgradeStatus Status + { + get { return _status; } + private set { _status = value; RaisePropertyChangedAuto(); } + } + + private long _current; + public long Current + { + get { return _current; } + internal set + { + _current = value; RaisePropertyChangedAuto(); + } + } + + private long _total; + public long Total + { + get { return _total; } + internal set { _total = value; RaisePropertyChangedAuto(); } + } + + public Task Cancel() + { + return Task.Factory.StartNew(() => + { + _cancelAction.Invoke(); + Status = FirmwareUpgradeStatus.Canceled; + }); + } + + internal void RaiseCompleted() + { + Status = FirmwareUpgradeStatus.Completed; + Completed?.Invoke(this, new EventArgs()); + } + + internal void RaiseCanceled() + { + Status = FirmwareUpgradeStatus.Canceled; + Canceled?.Invoke(this, new EventArgs()); + } + + internal void RaiseFailed(Exception ex) + { + Status = FirmwareUpgradeStatus.Failed; + Failed?.Invoke(this, ex); + } + + internal void RaiseProgress(long current, FirmwareUpgradeStatus status) + { + Current = current; + Status = status; + + Progress?.Invoke(this, new FirmwareUpgradeProgressEventArgs() + { + Current = Current, + Status = Status, + Total = Total + }); + } + } +} diff --git a/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeProgressEventArgs.cs b/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeProgressEventArgs.cs new file mode 100644 index 000000000..4e1c86fe6 --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeProgressEventArgs.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Integration.Operation +{ + public class FirmwareUpgradeProgressEventArgs : EventArgs + { + public long Current { get; set; } + public long Total { get; set; } + public FirmwareUpgradeStatus Status { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeStatus.cs b/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeStatus.cs new file mode 100644 index 000000000..e2c956807 --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeStatus.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Integration.Operation +{ + public enum FirmwareUpgradeStatus + { + [Description("Initializing...")] + Initializing, + [Description("Uploading MCU file...")] + UploadingMCU, + [Description("Uploading FPGA 1 file...")] + UploadingFPGA1, + [Description("Uploading FPGA 2 file...")] + UploadingFPGA2, + [Description("Uploading FPGA 3 file...")] + UploadingFPGA3, + [Description("Validating version integrity...")] + Validating, + [Description("Activating version...")] + Activating, + [Description("Waiting for device reboot...")] + WaitingForReboot, + [Description("Connecting...")] + Connecting, + [Description("Completed")] + Completed, + [Description("Aborted")] + Canceled, + [Description("Failed")] + Failed, + } +} diff --git a/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs index afbac482b..1495808cd 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs @@ -16,6 +16,7 @@ using Google.Protobuf; using Tango.PMR.Connection; using Tango.PMR.Stubs; using Tango.Integration.Storage; +using System.IO; namespace Tango.Integration.Operation { @@ -323,6 +324,13 @@ namespace Tango.Integration.Operation /// Task Reset(); + /// + /// Upgrades the firmware. + /// + /// The TFP stream (Tango Firmware Package File). + /// + Task UpgradeFirmware(Stream tfpStream); + /// /// Creates a storage manager for managing the machine file system. /// diff --git a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs index 6b6dca4c4..b3d8741b6 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs @@ -26,6 +26,9 @@ using Tango.BL.ColorConversion; using Tango.PMR.Stubs; using System.Threading; using Tango.Integration.Storage; +using Ionic.Zip; +using Tango.Core.Threading; +using Tango.PMR.IO; namespace Tango.Integration.Operation { @@ -36,6 +39,12 @@ namespace Tango.Integration.Operation /// public class MachineOperator : BasicTransporter, IMachineOperator { + private const String FIRMWARE_UPGRADE_FOLDER_NAME = "UpgradePackage"; + private const String FIRMWARE_MCU_FILE_NAME = "mcu"; + private const String FIRMWARE_FPGA1_FILE_NAME = "fpga1"; + private const String FIRMWARE_FPGA2_FILE_NAME = "fpga2"; + private const String FIRMWARE_FPGA3_FILE_NAME = "fpga3"; + private bool _diagnosticsSent; private bool _eventsSent; private bool _debugSent; @@ -718,6 +727,162 @@ namespace Tango.Integration.Operation #endregion + #region Private Methods + + private async void ResumeJob() + { + LogManager.Log("Checking if a job is in progress..."); + + try + { + var res = await SendRequest(new CurrentJobRequest()); + + if (res.Message.IsJobInProgress) + { + JobTicket jobTicket = res.Message.JobTicket; + + ProcessParametersTable processParameters = new ProcessParametersTable(); + jobTicket.ProcessParameters.MapPrimitivesTo(processParameters); + + ResumingJobEventArgs args = new ResumingJobEventArgs((job) => + { + if (Status != MachineStatuses.ReadyToDye) + { + throw new InvalidOperationException("Could not print while status = " + Status); + } + + RunningJob = null; + RunningJobStatus = null; + + var originalJob = job; + + CurrentProcessParameters = processParameters; + + if (job.NumberOfUnits < 1) + { + job.NumberOfUnits = 1; + } + + job = job.Clone(); + + var segments = job.Segments.ToList(); + + for (int i = 0; i < job.NumberOfUnits - 1; i++) + { + foreach (var s in segments) + { + job.Segments.Add(s); + } + } + + var request = new ResumeCurrentJobRequest(); + + JobHandler handler = null; + + handler = new JobHandler(async () => + { + try + { + var result = await SendRequest(new AbortJobRequest()); + PrintingAborted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + handler.RaiseCanceled(); + } + catch (Exception ex) + { + LogManager.Log(ex, "Failed to cancel job."); + } + }, originalJob, jobTicket, processParameters, JobHandlingMode); + + handler.StatusChanged += (x, s) => + { + RunningJobStatus = s; + }; + + LogRequestSent(request); + + bool responseLogged = false; + + SendContinuousRequest(request, null, TimeSpan.FromSeconds(2)).Subscribe((response) => + { + handler.RaiseStatusReceived(response.Message.Status); + + if (!responseLogged) + { + responseLogged = true; + Status = MachineStatuses.Printing; + RunningJob = originalJob; + PrintingStarted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + LogResponseReceived(response.Message); + } + }, (ex) => + { + if (!(ex is ContinuousResponseAbortedException)) + { + Status = MachineStatuses.ReadyToDye; + + if (!handler.IsCanceled) + { + PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(handler, originalJob, ex)); + handler.RaiseFailed(ex); + LogRequestFailed(request, ex); + } + } + else + { + Status = MachineStatuses.ReadyToDye; + } + }, () => + { + Status = MachineStatuses.ReadyToDye; + PrintingCompleted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + handler.RaiseCompleted(); + }); + + return handler; + }); + + args.JobGuid = jobTicket.Guid; + ResumingJob?.Invoke(this, args); + } + } + catch (Exception ex) + { + LogManager.Log(ex); + } + } + + /// + /// Logs the request sent. + /// + /// The message. + protected void LogRequestSent(IMessage message) + { + LogManager.Log(String.Format("Sending request '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString())); + OnRequestSent(message); + } + + /// + /// Logs the request failed. + /// + /// The message. + protected void LogRequestFailed(IMessage message, Exception ex) + { + LogManager.Log(String.Format("Request failed '{0}'...{1}{2}{1}{3}", message.GetType().Name, Environment.NewLine, message.ToJsonString(), ex.ToString()), LogCategory.Error); + OnRequestFailed(message, ex); + } + + /// + /// Logs the response received. + /// + /// The message. + protected void LogResponseReceived(IMessage message) + { + LogManager.Log(String.Format("Response received '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString())); + OnResponseReceived(message); + } + + #endregion + #region Public Methods /// @@ -912,40 +1077,40 @@ namespace Tango.Integration.Operation bool responseLogged = false; SendContinuousRequest(request, null, TimeSpan.FromSeconds(2)).Subscribe((response) => - { - handler.RaiseStatusReceived(response.Message.Status); - - if (!responseLogged) - { - responseLogged = true; - Status = MachineStatuses.Printing; - RunningJob = originalJob; - PrintingStarted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); - LogResponseReceived(response.Message); - } - }, (ex) => - { - if (!(ex is ContinuousResponseAbortedException)) - { - Status = MachineStatuses.ReadyToDye; - - if (!handler.IsCanceled) - { - PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(handler, originalJob, ex)); - handler.RaiseFailed(ex); - LogRequestFailed(request, ex); - } - } - else - { - Status = MachineStatuses.ReadyToDye; - } - }, () => - { - Status = MachineStatuses.ReadyToDye; - PrintingCompleted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); - handler.RaiseCompleted(); - }); + { + handler.RaiseStatusReceived(response.Message.Status); + + if (!responseLogged) + { + responseLogged = true; + Status = MachineStatuses.Printing; + RunningJob = originalJob; + PrintingStarted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + LogResponseReceived(response.Message); + } + }, (ex) => + { + if (!(ex is ContinuousResponseAbortedException)) + { + Status = MachineStatuses.ReadyToDye; + + if (!handler.IsCanceled) + { + PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(handler, originalJob, ex)); + handler.RaiseFailed(ex); + LogRequestFailed(request, ex); + } + } + else + { + Status = MachineStatuses.ReadyToDye; + } + }, () => + { + Status = MachineStatuses.ReadyToDye; + PrintingCompleted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); + handler.RaiseCompleted(); + }); return handler; } @@ -1602,160 +1767,186 @@ namespace Tango.Integration.Operation return new StorageManager(this); } - #endregion - - #region Private Methods - - private async void ResumeJob() + /// + /// Upgrades the firmware. + /// + /// The TFP stream (Tango Firmware Package File). + /// + public async Task UpgradeFirmware(Stream tfpStream) { - LogManager.Log("Checking if a job is in progress..."); + bool cancel = false; - try + var upgradeHandler = new FirmwareUpgradeHandler(() => { - var res = await SendRequest(new CurrentJobRequest()); - - if (res.Message.IsJobInProgress) - { - JobTicket jobTicket = res.Message.JobTicket; - - ProcessParametersTable processParameters = new ProcessParametersTable(); - jobTicket.ProcessParameters.MapPrimitivesTo(processParameters); - - ResumingJobEventArgs args = new ResumingJobEventArgs((job) => - { - if (Status != MachineStatuses.ReadyToDye) - { - throw new InvalidOperationException("Could not print while status = " + Status); - } - - RunningJob = null; - RunningJobStatus = null; + cancel = true; + }); - var originalJob = job; + ZipFile zip = ZipFile.Read(tfpStream); - CurrentProcessParameters = processParameters; - - if (job.NumberOfUnits < 1) - { - job.NumberOfUnits = 1; - } + //Perform zip validation... + if (!zip.Entries.ToList().Exists(x => x.FileName == FIRMWARE_MCU_FILE_NAME)) + { + throw new IOException($"Invalid firmware upgrade package. file {FIRMWARE_MCU_FILE_NAME} could not be found."); + } - job = job.Clone(); + if (!zip.Entries.ToList().Exists(x => x.FileName == FIRMWARE_FPGA1_FILE_NAME)) + { + throw new IOException($"Invalid firmware upgrade package. file {FIRMWARE_FPGA1_FILE_NAME} could not be found."); + } - var segments = job.Segments.ToList(); + if (!zip.Entries.ToList().Exists(x => x.FileName == FIRMWARE_FPGA2_FILE_NAME)) + { + throw new IOException($"Invalid firmware upgrade package. file {FIRMWARE_FPGA2_FILE_NAME} could not be found."); + } - for (int i = 0; i < job.NumberOfUnits - 1; i++) - { - foreach (var s in segments) - { - job.Segments.Add(s); - } - } + if (!zip.Entries.ToList().Exists(x => x.FileName == FIRMWARE_FPGA3_FILE_NAME)) + { + throw new IOException($"Invalid firmware upgrade package. file {FIRMWARE_FPGA3_FILE_NAME} could not be found."); + } - var request = new ResumeCurrentJobRequest(); + upgradeHandler.Total = zip.Entries.Sum(x => x.UncompressedSize); - JobHandler handler = null; + var storage = CreateStorageManager(); + var drive = await storage.GetStorageDrive(); + var root = await storage.GetRootFolder(); + var existing_folder = root.Items.SingleOrDefault(x => x.Name == FIRMWARE_UPGRADE_FOLDER_NAME); + if (existing_folder != null) + { + await storage.DeleteItem(existing_folder); + } - handler = new JobHandler(async () => - { - try - { - var result = await SendRequest(new AbortJobRequest()); - PrintingAborted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); - handler.RaiseCanceled(); - } - catch (Exception ex) - { - LogManager.Log(ex, "Failed to cancel job."); - } - }, originalJob, jobTicket, processParameters, JobHandlingMode); + String package_folder = Path.Combine(drive.Root, FIRMWARE_UPGRADE_FOLDER_NAME); - handler.StatusChanged += (x, s) => - { - RunningJobStatus = s; - }; + await storage.CreateFolder(package_folder); - LogRequestSent(request); + List handlers = new List(); + List entries = zip.Entries.ToList(); + List streams = new List(); - bool responseLogged = false; + Action uploadNext = null; + Action validate = null; + Action activate = null; + Action postActivation = null; - SendContinuousRequest(request, null, TimeSpan.FromSeconds(2)).Subscribe((response) => + uploadNext = new Action(() => + { + if (entries.Count > 0) + { + try + { + var entry = entries.First(); + entries.Remove(entry); + + var reader = entry.OpenReader(); + streams.Add(reader); + + var handler = storage.UploadFile(Path.Combine(package_folder, entry.FileName), reader).Result; + handlers.Add(handler); + handler.Canceled += (_, __) => { upgradeHandler.RaiseCanceled(); cancel = true; }; + handler.Completed += (_, __) => uploadNext(); + handler.Failed += (_, failedEx) => { upgradeHandler.RaiseFailed(failedEx); cancel = true; }; + handler.Progress += (_, e) => { - handler.RaiseStatusReceived(response.Message.Status); - - if (!responseLogged) + if (cancel) { - responseLogged = true; - Status = MachineStatuses.Printing; - RunningJob = originalJob; - PrintingStarted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); - LogResponseReceived(response.Message); + handler.Cancel(); + return; } - }, (ex) => - { - if (!(ex is ContinuousResponseAbortedException)) - { - Status = MachineStatuses.ReadyToDye; - if (!handler.IsCanceled) - { - PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(handler, originalJob, ex)); - handler.RaiseFailed(ex); - LogRequestFailed(request, ex); - } - } - else + switch (entry.FileName) { - Status = MachineStatuses.ReadyToDye; + case FIRMWARE_MCU_FILE_NAME: + upgradeHandler.RaiseProgress(upgradeHandler.Current + e.Delta, FirmwareUpgradeStatus.UploadingMCU); + break; + case FIRMWARE_FPGA1_FILE_NAME: + upgradeHandler.RaiseProgress(upgradeHandler.Current + e.Delta, FirmwareUpgradeStatus.UploadingFPGA1); + break; + case FIRMWARE_FPGA2_FILE_NAME: + upgradeHandler.RaiseProgress(upgradeHandler.Current + e.Delta, FirmwareUpgradeStatus.UploadingFPGA2); + break; + case FIRMWARE_FPGA3_FILE_NAME: + upgradeHandler.RaiseProgress(upgradeHandler.Current + e.Delta, FirmwareUpgradeStatus.UploadingFPGA3); + break; } - }, () => - { - Status = MachineStatuses.ReadyToDye; - PrintingCompleted?.Invoke(this, new PrintingEventArgs(handler, originalJob)); - handler.RaiseCompleted(); - }); + }; + } + catch (Exception ex) + { + upgradeHandler.RaiseFailed(ex); + } + } + else + { + validate(); + } + }); - return handler; - }); + List descriptors = new List(); + descriptors.Add(new VersionFileDescriptor() + { + FileName = Path.Combine(package_folder, FIRMWARE_MCU_FILE_NAME), + Destination = VersionFileDestination.Mcu, + }); + descriptors.Add(new VersionFileDescriptor() + { + FileName = Path.Combine(package_folder, FIRMWARE_FPGA1_FILE_NAME), + Destination = VersionFileDestination.Fpga1, + }); + descriptors.Add(new VersionFileDescriptor() + { + FileName = Path.Combine(package_folder, FIRMWARE_FPGA2_FILE_NAME), + Destination = VersionFileDestination.Fpga2, + }); + descriptors.Add(new VersionFileDescriptor() + { + FileName = Path.Combine(package_folder, FIRMWARE_FPGA3_FILE_NAME), + Destination = VersionFileDestination.Fpga3, + }); - args.JobGuid = jobTicket.Guid; - ResumingJob?.Invoke(this, args); + validate = new Action(() => + { + try + { + streams.ForEach(x => x.Dispose()); + upgradeHandler.RaiseProgress(upgradeHandler.Total, FirmwareUpgradeStatus.Validating); + var validateRequest = new ValidateVersionRequest(); + validateRequest.FileDescriptors.AddRange(descriptors); + var validateResponse = SendRequest(validateRequest, TimeSpan.FromSeconds(10)).Result; + activate(); } - } - catch (Exception ex) + catch (Exception ex) + { + upgradeHandler.RaiseFailed(ex); + } + }); + + activate = new Action(() => { - LogManager.Log(ex); - } - } + try + { + upgradeHandler.RaiseProgress(upgradeHandler.Total, FirmwareUpgradeStatus.Activating); + var activateRequest = new ActivateVersionRequest(); + activateRequest.FileDescriptors.AddRange(descriptors); + var activateResponse = SendRequest(activateRequest, TimeSpan.FromSeconds(10)).Result; + postActivation(); + } + catch (Exception ex) + { + upgradeHandler.RaiseFailed(ex); + } + }); - /// - /// Logs the request sent. - /// - /// The message. - protected void LogRequestSent(IMessage message) - { - LogManager.Log(String.Format("Sending request '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString())); - OnRequestSent(message); - } + postActivation = new Action(() => + { + upgradeHandler.RaiseCompleted(); + }); - /// - /// Logs the request failed. - /// - /// The message. - protected void LogRequestFailed(IMessage message, Exception ex) - { - LogManager.Log(String.Format("Request failed '{0}'...{1}{2}{1}{3}", message.GetType().Name, Environment.NewLine, message.ToJsonString(), ex.ToString()), LogCategory.Error); - OnRequestFailed(message, ex); - } + ThreadFactory.StartNew(() => + { + uploadNext(); + }); - /// - /// Logs the response received. - /// - /// The message. - protected void LogResponseReceived(IMessage message) - { - LogManager.Log(String.Format("Response received '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString())); - OnResponseReceived(message); + return upgradeHandler; } #endregion diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandler.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandler.cs index 6a9c5cae4..eaa209e65 100644 --- a/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandler.cs +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandler.cs @@ -42,11 +42,13 @@ namespace Tango.Integration.Storage get { return _current; } internal set { + long previous = _current; _current = value; RaisePropertyChangedAuto(); Progress?.Invoke(this, new StorageFileHandlerProgressEventArgs() { Current = _current, Total = _total, + Delta = _current - previous, }); if (Status != StorageFileHandlerStatus.Active) diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandlerProgressEventArgs.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandlerProgressEventArgs.cs index b873ff7b3..51e293535 100644 --- a/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandlerProgressEventArgs.cs +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageFileHandlerProgressEventArgs.cs @@ -9,6 +9,7 @@ namespace Tango.Integration.Storage public class StorageFileHandlerProgressEventArgs : EventArgs { public long Current { get; set; } + public long Delta { get; set; } public long Total { get; set; } } } diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs index c092b5bda..0743fe54d 100644 --- a/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs @@ -253,13 +253,7 @@ namespace Tango.Integration.Storage } else { - var a = _transporter.SendRequest(new FileChunkUploadRequest() - { - IsCanceled = true, - }).Result; - handler.RaiseCanceled(); - return; } } diff --git a/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj b/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj index 8498219bc..14cdc03c5 100644 --- a/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj +++ b/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj @@ -39,6 +39,9 @@ ..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.dll + + ..\packages\Ionic.Zip.1.9.1.8\lib\Ionic.Zip.dll + ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll @@ -86,6 +89,9 @@ + + + @@ -160,7 +166,7 @@ - + \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Integration/packages.config b/Software/Visual_Studio/Tango.Integration/packages.config index 826cafd8b..5f277f7aa 100644 --- a/Software/Visual_Studio/Tango.Integration/packages.config +++ b/Software/Visual_Studio/Tango.Integration/packages.config @@ -2,6 +2,7 @@ + diff --git a/Software/Visual_Studio/Utilities/Tango.Stubs.UI/App.config b/Software/Visual_Studio/Utilities/Tango.Stubs.UI/App.config index 5ea2123d1..9b987cd67 100644 --- a/Software/Visual_Studio/Utilities/Tango.Stubs.UI/App.config +++ b/Software/Visual_Studio/Utilities/Tango.Stubs.UI/App.config @@ -101,6 +101,50 @@ --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.3.1 From a2d959a7777bf2387d0f50dbc1ecf69f53e2253d Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Sun, 2 Dec 2018 16:37:25 +0200 Subject: Implemented machine studio storage module. firmware upgrade version/validate/activate. Implemented firmware package generator utility. --- Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 20578304 -> 20578304 bytes .../PMR/Messages/IO/ActivateVersionRequest.proto | 4 +- .../PMR/Messages/IO/ValidateVersionRequest.proto | 4 +- .../PMR/Messages/IO/VersionPackageDescriptor.proto | 11 + .../ViewModels/MainViewVM.cs | 38 +++ .../Views/MainView.xaml | 4 +- .../FirmwareUpgrade/IFirmwareUpgrader.cs | 1 + .../FirmwareUpgrade/DefaultFirmwareUpgrader.cs | 5 +- .../Tango.MachineStudio.UI.csproj | 2 +- .../ViewModels/FirmwareUpgradeViewVM.cs | 87 +++++-- .../Views/FirmwareUpgradeView.xaml | 15 +- .../ExtensionMethods/ExceptionExtensions.cs | 21 ++ .../ExtensionMethods/ObjectExtensions.cs | 1 + .../Tango.Core/Json/ProtobufContractResolver.cs | 24 ++ .../Visual_Studio/Tango.Core/Tango.Core.csproj | 3 +- .../Tango.Emulations/Emulators/MachineEmulator.cs | 45 +++- .../Operation/FirmwareUpgradeHandler.cs | 94 ------- .../Operation/FirmwareUpgradeProgressEventArgs.cs | 15 -- .../Operation/FirmwareUpgradeStatus.cs | 37 --- .../Operation/IMachineOperator.cs | 21 ++ .../Tango.Integration/Operation/MachineOperator.cs | 276 ++++++++++----------- .../Tango.Integration/Storage/StorageManager.cs | 1 + .../Tango.Integration/Tango.Integration.csproj | 6 +- .../Upgrade/FirmwareUpgradeHandler.cs | 108 ++++++++ .../Upgrade/FirmwareUpgradeProgressEventArgs.cs | 16 ++ .../Upgrade/FirmwareUpgradeStatus.cs | 31 +++ .../Tango.PMR/IO/ActivateVersionRequest.cs | 48 ++-- .../Tango.PMR/IO/ValidateVersionRequest.cs | 48 ++-- .../Tango.PMR/IO/VersionPackageDescriptor.cs | 153 ++++++++++++ Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj | 3 +- .../Tango.Transport/TransporterBase.cs | 29 ++- Software/Visual_Studio/Tango.sln | 55 +++- .../Tango.FirmwarePackageGenerator/App.config | 50 ++++ .../Tango.FirmwarePackageGenerator/App.xaml | 25 ++ .../Tango.FirmwarePackageGenerator/App.xaml.cs | 17 ++ .../Images/firmware_upgrade.png | Bin 0 -> 52803 bytes .../Tango.FirmwarePackageGenerator/MainWindow.xaml | 41 +++ .../MainWindow.xaml.cs | 43 ++++ .../Tango.FirmwarePackageGenerator/MainWindowVM.cs | 103 ++++++++ .../Properties/AssemblyInfo.cs | 7 + .../Properties/Resources.Designer.cs | 71 ++++++ .../Properties/Resources.resx | 117 +++++++++ .../Properties/Settings.Designer.cs | 30 +++ .../Properties/Settings.settings | 7 + .../Tango.FirmwarePackageGenerator.csproj | 134 ++++++++++ .../VersionFileModel.cs | 44 ++++ .../Tango.FirmwarePackageGenerator/packages.config | 6 + 48 files changed, 1508 insertions(+), 393 deletions(-) create mode 100644 Software/PMR/Messages/IO/VersionPackageDescriptor.proto create mode 100644 Software/Visual_Studio/Tango.Core/Json/ProtobufContractResolver.cs delete mode 100644 Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeHandler.cs delete mode 100644 Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeProgressEventArgs.cs delete mode 100644 Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeStatus.cs create mode 100644 Software/Visual_Studio/Tango.Integration/Upgrade/FirmwareUpgradeHandler.cs create mode 100644 Software/Visual_Studio/Tango.Integration/Upgrade/FirmwareUpgradeProgressEventArgs.cs create mode 100644 Software/Visual_Studio/Tango.Integration/Upgrade/FirmwareUpgradeStatus.cs create mode 100644 Software/Visual_Studio/Tango.PMR/IO/VersionPackageDescriptor.cs create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/App.config create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/App.xaml create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/App.xaml.cs create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Images/firmware_upgrade.png create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/MainWindow.xaml create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/MainWindow.xaml.cs create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/MainWindowVM.cs create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/AssemblyInfo.cs create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Resources.Designer.cs create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Resources.resx create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Settings.Designer.cs create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Settings.settings create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Tango.FirmwarePackageGenerator.csproj create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/VersionFileModel.cs create mode 100644 Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/packages.config (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels') diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index 355832ca0..ff9e90053 100644 Binary files a/Software/DB/Tango.mdf and b/Software/DB/Tango.mdf differ diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf index e4f508570..07da3d430 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/PMR/Messages/IO/ActivateVersionRequest.proto b/Software/PMR/Messages/IO/ActivateVersionRequest.proto index cc82e673c..6b6579197 100644 --- a/Software/PMR/Messages/IO/ActivateVersionRequest.proto +++ b/Software/PMR/Messages/IO/ActivateVersionRequest.proto @@ -1,11 +1,9 @@ syntax = "proto3"; -import "VersionFileDescriptor.proto"; - package Tango.PMR.IO; option java_package = "com.twine.tango.pmr.io"; message ActivateVersionRequest { - repeated VersionFileDescriptor FileDescriptors = 1; + string Path = 1; } \ No newline at end of file diff --git a/Software/PMR/Messages/IO/ValidateVersionRequest.proto b/Software/PMR/Messages/IO/ValidateVersionRequest.proto index 7a0c080ec..9bc2ff0d5 100644 --- a/Software/PMR/Messages/IO/ValidateVersionRequest.proto +++ b/Software/PMR/Messages/IO/ValidateVersionRequest.proto @@ -1,11 +1,9 @@ syntax = "proto3"; -import "VersionFileDescriptor.proto"; - package Tango.PMR.IO; option java_package = "com.twine.tango.pmr.io"; message ValidateVersionRequest { - repeated VersionFileDescriptor FileDescriptors = 1; + string Path = 1; } \ No newline at end of file diff --git a/Software/PMR/Messages/IO/VersionPackageDescriptor.proto b/Software/PMR/Messages/IO/VersionPackageDescriptor.proto new file mode 100644 index 000000000..1b67b8062 --- /dev/null +++ b/Software/PMR/Messages/IO/VersionPackageDescriptor.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +import "VersionFileDescriptor.proto"; + +package Tango.PMR.IO; +option java_package = "com.twine.tango.pmr.io"; + +message VersionPackageDescriptor +{ + repeated VersionFileDescriptor FileDescriptors = 1; +} \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs index a9cfed937..4db48c636 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs @@ -75,6 +75,10 @@ namespace Tango.MachineStudio.Storage.ViewModels public RelayCommand UploadVersionCommand { get; set; } + public RelayCommand ValidateVersionCommand { get; set; } + + public RelayCommand ActivateVersionCommand { get; set; } + public MainViewVM(IStudioApplicationManager applicationManager, INotificationProvider notificationProvider, IFirmwareUpgrader firmwareUpgrader) { _applicationManager = applicationManager; @@ -96,6 +100,8 @@ namespace Tango.MachineStudio.Storage.ViewModels DeleteFolderCommand = new RelayCommand(DeleteFolder, () => StorageManager != null && SelectedStorageItem != null && SelectedStorageItem is StorageFolder); UploadFileCommand = new RelayCommand(UploadFile, () => StorageManager != null && StorageManager.CurrentFolder != null); UploadVersionCommand = new RelayCommand(UploadVersion, () => StorageManager != null && StorageManager.CurrentFolder != null); + ValidateVersionCommand = new RelayCommand(ValidateVersion, () => StorageManager != null && StorageManager.CurrentFolder != null); + ActivateVersionCommand = new RelayCommand(ActivateVersion, () => StorageManager != null && StorageManager.CurrentFolder != null); } private void UploadFile() @@ -362,5 +368,37 @@ namespace Tango.MachineStudio.Storage.ViewModels { _firmwareUpgrader.InvokeUpgradeUI(); } + + private async void ValidateVersion() + { + using (_notification.PushTaskItem("Validating firmware version...")) + { + try + { + await _applicationManager.ConnectedMachine.ValidateFirmwareVersion(StorageManager.CurrentPath); + _notification.ShowInfo($"Version validated successfully!"); + } + catch (Exception ex) + { + _notification.ShowError($"Error validating firmware version.\n{ex.FlattenMessage()}"); + } + } + } + + private async void ActivateVersion() + { + using (_notification.PushTaskItem("Activating firmware version...")) + { + try + { + await _applicationManager.ConnectedMachine.ActivateFirmwareVersion(StorageManager.CurrentPath); + _notification.ShowInfo($"Version activated successfully!"); + } + catch (Exception ex) + { + _notification.ShowError($"Error activating firmware version.\n{ex.FlattenMessage()}"); + } + } + } } } diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml index 1f435b696..e59837d49 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml @@ -68,13 +68,13 @@ UPGRADE VERSION - - public void InvokeUpgradeUI() { - FirmwareUpgradeViewVM vm = new FirmwareUpgradeViewVM(_applicationManager.ConnectedMachine); + FirmwareUpgradeViewVM vm = new FirmwareUpgradeViewVM(_applicationManager.ConnectedMachine, _notification); - _notification.ShowModalDialog(vm, (x) => + _notification.ShowModalDialog(vm, (x) => { }, () => { }); diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index a9a0e1bb9..b3926190f 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -609,7 +609,7 @@ copy /Y "$(SolutionDir)Referenced Assemblies\Microsoft.WITDataStore32.dll" "$(Ta - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/FirmwareUpgradeViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/FirmwareUpgradeViewVM.cs index ce8b09aa4..09b63cfc9 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/FirmwareUpgradeViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/FirmwareUpgradeViewVM.cs @@ -7,6 +7,8 @@ using System.Text; using System.Threading.Tasks; using Tango.Core.Commands; using Tango.Integration.Operation; +using Tango.Integration.Upgrade; +using Tango.MachineStudio.Common.Notifications; using Tango.SharedUI; namespace Tango.MachineStudio.UI.ViewModels @@ -14,6 +16,7 @@ namespace Tango.MachineStudio.UI.ViewModels public class FirmwareUpgradeViewVM : DialogViewVM { private IMachineOperator _operator; + private INotificationProvider _notification; private FileStream _stream; private FirmwareUpgradeHandler _handler; @@ -37,27 +40,50 @@ namespace Tango.MachineStudio.UI.ViewModels set { _currentPage = value; RaisePropertyChangedAuto(); } } + private String upgradeError; + public String UpgradeError + { + get { return upgradeError; } + set { upgradeError = value; RaisePropertyChangedAuto(); } + } + + public RelayCommand SelectCommand { get; set; } public RelayCommand UpgradeCommand { get; set; } public RelayCommand AbortCommand { get; set; } - public FirmwareUpgradeViewVM(IMachineOperator machineOperator) : base() + public FirmwareUpgradeViewVM(IMachineOperator machineOperator, INotificationProvider notificationProvider) : base() { + _notification = notificationProvider; _operator = machineOperator; SelectCommand = new RelayCommand(BrowseForFile); UpgradeCommand = new RelayCommand(StartUpgrade, () => SelectedFile != null); AbortCommand = new RelayCommand(AbortUpgrade, () => Handler != null && Handler.Status != FirmwareUpgradeStatus.Validating && Handler.Status != FirmwareUpgradeStatus.Activating); } - private void BrowseForFile() + private async void BrowseForFile() { OpenFileDialog dlg = new OpenFileDialog(); dlg.Title = "Select tango firmware package file"; dlg.Filter = "Tango Firmware Package|*.tfp"; if (dlg.ShowDialog().Value) { + try + { + using (FileStream fs = new FileStream(dlg.FileName, FileMode.Open)) + { + var info = await _operator.GetFirmwarePackageInfo(fs); + } + } + catch (Exception ex) + { + LogManager.Log(ex); + _notification.ShowError("The selected package seems to be invalid."); + return; + } + SelectedFile = dlg.FileName; InvalidateRelayCommands(); } @@ -65,36 +91,53 @@ namespace Tango.MachineStudio.UI.ViewModels private async void StartUpgrade() { + CanClose = false; CurrentPage = 1; - _stream = new FileStream(SelectedFile, FileMode.Open); - Handler = await _operator.UpgradeFirmware(_stream); - Handler.Progress += (_, e) => + try { - InvokeUI(() => + _stream = new FileStream(SelectedFile, FileMode.Open); + Handler = await _operator.UpgradeFirmware(_stream); + Handler.Progress += (_, e) => { - AbortCommand.RaiseCanExecuteChanged(); - }); - }; - Handler.Completed += (_, __) => - { - _stream.Dispose(); - CurrentPage = 2; - }; - Handler.Canceled += (_, __) => - { - _stream.Dispose(); - }; - Handler.Failed += (_, __) => + InvokeUI(() => + { + AbortCommand.RaiseCanExecuteChanged(); + }); + }; + Handler.Completed += (_, __) => + { + CanClose = true; + _stream.Dispose(); + CurrentPage = 2; + }; + Handler.Canceled += (_, __) => + { + CanClose = true; + _stream.Dispose(); + CurrentPage = 0; + }; + Handler.Failed += (_, ex) => + { + UpgradeError = ex.FlattenMessage(); + CanClose = true; + _stream.Dispose(); + CurrentPage = 3; + }; + } + catch (Exception ex) { - _stream.Dispose(); - }; - + CanClose = true; + UpgradeError = ex.FlattenMessage(); + CurrentPage = 3; + } } private async void AbortUpgrade() { + CanClose = true; await Handler.Cancel(); + CurrentPage = 0; } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/FirmwareUpgradeView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/FirmwareUpgradeView.xaml index b69ad6a5b..84f4b2d92 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/FirmwareUpgradeView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/FirmwareUpgradeView.xaml @@ -43,9 +43,9 @@ - The upgrade wizard will help you upgrade the connected machine firmware version. + This upgrade wizard will help you upgrade the connected machine firmware version. - Press 'SELECT' to browse for a .tfp file (Tango Firmware Package). + Press 'SELECT' to browse for an .tfp file (Tango Firmware Package). @@ -67,7 +67,7 @@ Upgrading Machine Firmware - + @@ -80,6 +80,15 @@ + + + + Firmware Upgrade Failed + + + + + diff --git a/Software/Visual_Studio/Tango.Core/ExtensionMethods/ExceptionExtensions.cs b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ExceptionExtensions.cs index fdb041ea9..86434cdc4 100644 --- a/Software/Visual_Studio/Tango.Core/ExtensionMethods/ExceptionExtensions.cs +++ b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ExceptionExtensions.cs @@ -29,5 +29,26 @@ public static class ExceptionExtensions return stringBuilder.ToString(); } + + /// + /// Flattens the exception message in case it is an aggregated exception. + /// + /// The exception. + /// + public static String FlattenMessage(this Exception exception) + { + String message = exception.Message; + + if (exception is AggregateException) + { + try + { + message += Environment.NewLine + String.Join(Environment.NewLine, (exception as AggregateException).InnerExceptions.Select(x => x.Message)); + } + catch { } + } + + return message; + } } diff --git a/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs index cff4e6a3a..0ce3e8369 100644 --- a/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs +++ b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs @@ -132,6 +132,7 @@ public static class ObjectExtensions { var settings = new JsonSerializerSettings(); settings.Converters.Add(new StringEnumConverter { CamelCaseText = false }); + settings.ContractResolver = new ProtobufContractResolver(); return settings; }); diff --git a/Software/Visual_Studio/Tango.Core/Json/ProtobufContractResolver.cs b/Software/Visual_Studio/Tango.Core/Json/ProtobufContractResolver.cs new file mode 100644 index 000000000..4921114af --- /dev/null +++ b/Software/Visual_Studio/Tango.Core/Json/ProtobufContractResolver.cs @@ -0,0 +1,24 @@ +using Google.Protobuf; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Core.Json +{ + public class ProtobufContractResolver : DefaultContractResolver + { + protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + { + JsonProperty property = base.CreateProperty(member, memberSerialization); + + property.ShouldSerialize = (x) => property.PropertyType != typeof(ByteString); + + return property; + } + } +} diff --git a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj index 16451aa4e..469a17cd9 100644 --- a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj +++ b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj @@ -86,6 +86,7 @@ GlobalVersionInfo.cs + @@ -191,7 +192,7 @@ - + diff --git a/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs b/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs index 4a0758a4c..91868d85c 100644 --- a/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs +++ b/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs @@ -27,6 +27,7 @@ using Tango.PMR.Hardware; using System.Runtime.InteropServices; using Tango.PMR.IO; using System.IO; +using Tango.Integration.Operation; namespace Tango.Emulations.Emulators { @@ -44,6 +45,7 @@ namespace Tango.Emulations.Emulators public bool Canceled { get; set; } } + private const int MAX_CHUNK_LENGTH = 1024 * 10; private StartDiagnosticsRequest _diagnosticsRequest; private bool _cancelJob; private List _motorJoggingRequestTypes; @@ -193,7 +195,10 @@ namespace Tango.Emulations.Emulators /// The container. protected override void OnTransporterRequestReceived(object sender, MessageContainer container) { - LogManager.Log(container.Type.ToString().ToWords() + " received." + Environment.NewLine + MessageFactory.ExtractMessageFromContainer(container).ToJsonString()); + if (container.Type != MessageType.FileChunkUploadRequest && container.Type != MessageType.FileChunkDownloadRequest) + { + LogManager.Log(container.Type.ToString().ToWords() + " received." + Environment.NewLine + MessageFactory.ExtractMessageFromContainer(container).ToJsonString()); + } if (PerformNativeRoundTrip) { @@ -1057,7 +1062,7 @@ namespace Tango.Emulations.Emulators Transporter.SendResponse(new FileDownloadResponse() { DownloadID = Guid.NewGuid().ToString(), - MaxChunkLength = Math.Min(1024, length), + MaxChunkLength = Math.Min(MAX_CHUNK_LENGTH, length), }, request.Container.Token, null, File.Exists(request.Message.FileName) ? ErrorCode.None : ErrorCode.FileNotFound); } @@ -1070,7 +1075,7 @@ namespace Tango.Emulations.Emulators using (FileStream fs = new FileStream(message.FileName, FileMode.Open)) { fs.Position = message.Position; - byte[] buffer = new byte[Math.Min(1024, fs.Length - fs.Position)]; + byte[] buffer = new byte[Math.Min(MAX_CHUNK_LENGTH, fs.Length - fs.Position)]; fs.Read(buffer, 0, buffer.Length); Transporter.SendResponse(new FileChunkDownloadResponse() { @@ -1126,7 +1131,7 @@ namespace Tango.Emulations.Emulators var message = request.Message; Transporter.SendResponse(new FileUploadResponse() { - MaxChunkLength = 1024, + MaxChunkLength = MAX_CHUNK_LENGTH, UploadID = Guid.NewGuid().ToString(), }, request.Container.Token); } @@ -1153,10 +1158,23 @@ namespace Tango.Emulations.Emulators private void HandleValidateVersionRequest(TangoMessage request) { - Task.Factory.StartNew(() => + Task.Factory.StartNew(() => { Thread.Sleep(3000); - Transporter.SendResponse(new ValidateVersionResponse(), request.Container.Token); + + try + { + using (FileStream fs = new FileStream(Path.Combine(request.Message.Path, MachineOperator.FIRMWARE_UPGRADE_CONFIG_FILE_NAME), FileMode.Open)) + { + VersionPackageDescriptor package = VersionPackageDescriptor.Parser.ParseFrom(fs); + } + + Transporter.SendResponse(new ValidateVersionResponse(), request.Container.Token); + } + catch (Exception ex) + { + Transporter.SendResponse(new ValidateVersionResponse(), request.Container.Token, null, ErrorCode.GeneralError, ex.Message); + } }); } @@ -1165,7 +1183,20 @@ namespace Tango.Emulations.Emulators Task.Factory.StartNew(() => { Thread.Sleep(3000); - Transporter.SendResponse(new ActivateVersionResponse(), request.Container.Token); + + try + { + using (FileStream fs = new FileStream(Path.Combine(request.Message.Path, MachineOperator.FIRMWARE_UPGRADE_CONFIG_FILE_NAME), FileMode.Open)) + { + VersionPackageDescriptor package = VersionPackageDescriptor.Parser.ParseFrom(fs); + } + + Transporter.SendResponse(new ActivateVersionResponse(), request.Container.Token); + } + catch (Exception ex) + { + Transporter.SendResponse(new ActivateVersionResponse(), request.Container.Token, null, ErrorCode.GeneralError, ex.Message); + } }); } diff --git a/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeHandler.cs b/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeHandler.cs deleted file mode 100644 index f944a2587..000000000 --- a/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeHandler.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.Core; -using Tango.Integration.Storage; - -namespace Tango.Integration.Operation -{ - public class FirmwareUpgradeHandler : ExtendedObject - { - private Action _cancelAction; - - public event EventHandler Progress; - public event EventHandler Completed; - public event EventHandler Canceled; - public event EventHandler Failed; - - internal FirmwareUpgradeHandler() - { - - } - - internal FirmwareUpgradeHandler(Action cancelAction) - { - _cancelAction = cancelAction; - } - - private FirmwareUpgradeStatus _status; - public FirmwareUpgradeStatus Status - { - get { return _status; } - private set { _status = value; RaisePropertyChangedAuto(); } - } - - private long _current; - public long Current - { - get { return _current; } - internal set - { - _current = value; RaisePropertyChangedAuto(); - } - } - - private long _total; - public long Total - { - get { return _total; } - internal set { _total = value; RaisePropertyChangedAuto(); } - } - - public Task Cancel() - { - return Task.Factory.StartNew(() => - { - _cancelAction.Invoke(); - Status = FirmwareUpgradeStatus.Canceled; - }); - } - - internal void RaiseCompleted() - { - Status = FirmwareUpgradeStatus.Completed; - Completed?.Invoke(this, new EventArgs()); - } - - internal void RaiseCanceled() - { - Status = FirmwareUpgradeStatus.Canceled; - Canceled?.Invoke(this, new EventArgs()); - } - - internal void RaiseFailed(Exception ex) - { - Status = FirmwareUpgradeStatus.Failed; - Failed?.Invoke(this, ex); - } - - internal void RaiseProgress(long current, FirmwareUpgradeStatus status) - { - Current = current; - Status = status; - - Progress?.Invoke(this, new FirmwareUpgradeProgressEventArgs() - { - Current = Current, - Status = Status, - Total = Total - }); - } - } -} diff --git a/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeProgressEventArgs.cs b/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeProgressEventArgs.cs deleted file mode 100644 index 4e1c86fe6..000000000 --- a/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeProgressEventArgs.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Tango.Integration.Operation -{ - public class FirmwareUpgradeProgressEventArgs : EventArgs - { - public long Current { get; set; } - public long Total { get; set; } - public FirmwareUpgradeStatus Status { get; set; } - } -} diff --git a/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeStatus.cs b/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeStatus.cs deleted file mode 100644 index e2c956807..000000000 --- a/Software/Visual_Studio/Tango.Integration/Operation/FirmwareUpgradeStatus.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Tango.Integration.Operation -{ - public enum FirmwareUpgradeStatus - { - [Description("Initializing...")] - Initializing, - [Description("Uploading MCU file...")] - UploadingMCU, - [Description("Uploading FPGA 1 file...")] - UploadingFPGA1, - [Description("Uploading FPGA 2 file...")] - UploadingFPGA2, - [Description("Uploading FPGA 3 file...")] - UploadingFPGA3, - [Description("Validating version integrity...")] - Validating, - [Description("Activating version...")] - Activating, - [Description("Waiting for device reboot...")] - WaitingForReboot, - [Description("Connecting...")] - Connecting, - [Description("Completed")] - Completed, - [Description("Aborted")] - Canceled, - [Description("Failed")] - Failed, - } -} diff --git a/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs index 1495808cd..831b601be 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs @@ -17,6 +17,8 @@ using Tango.PMR.Connection; using Tango.PMR.Stubs; using Tango.Integration.Storage; using System.IO; +using Tango.Integration.Upgrade; +using Tango.PMR.IO; namespace Tango.Integration.Operation { @@ -331,6 +333,25 @@ namespace Tango.Integration.Operation /// Task UpgradeFirmware(Stream tfpStream); + /// + /// Directs the embedded device to validate the last uploaded firmware package. + /// + /// + Task ValidateFirmwareVersion(String path); + + /// + /// Directs the embedded device to validate the last uploaded firmware package. + /// + /// + Task ActivateFirmwareVersion(String path); + + /// + /// Gets the firmware update package info. + /// + /// The TFP (Tango Firmware Package File) stream. + /// + Task GetFirmwarePackageInfo(Stream tfpStream); + /// /// Creates a storage manager for managing the machine file system. /// diff --git a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs index b3d8741b6..50bce46c2 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs @@ -29,6 +29,7 @@ using Tango.Integration.Storage; using Ionic.Zip; using Tango.Core.Threading; using Tango.PMR.IO; +using Tango.Integration.Upgrade; namespace Tango.Integration.Operation { @@ -39,11 +40,8 @@ namespace Tango.Integration.Operation /// public class MachineOperator : BasicTransporter, IMachineOperator { - private const String FIRMWARE_UPGRADE_FOLDER_NAME = "UpgradePackage"; - private const String FIRMWARE_MCU_FILE_NAME = "mcu"; - private const String FIRMWARE_FPGA1_FILE_NAME = "fpga1"; - private const String FIRMWARE_FPGA2_FILE_NAME = "fpga2"; - private const String FIRMWARE_FPGA3_FILE_NAME = "fpga3"; + public const String FIRMWARE_UPGRADE_FOLDER_NAME = "UpgradePackage"; + public const String FIRMWARE_UPGRADE_CONFIG_FILE_NAME = "package.cfg"; private bool _diagnosticsSent; private bool _eventsSent; @@ -1775,178 +1773,176 @@ namespace Tango.Integration.Operation public async Task UpgradeFirmware(Stream tfpStream) { bool cancel = false; + ZipFile zip = null; - var upgradeHandler = new FirmwareUpgradeHandler(() => + var upgradeHandler = new FirmwareUpgradeHandler(() => { cancel = true; }); - ZipFile zip = ZipFile.Read(tfpStream); - - //Perform zip validation... - if (!zip.Entries.ToList().Exists(x => x.FileName == FIRMWARE_MCU_FILE_NAME)) + try { - throw new IOException($"Invalid firmware upgrade package. file {FIRMWARE_MCU_FILE_NAME} could not be found."); - } + zip = ZipFile.Read(tfpStream); - if (!zip.Entries.ToList().Exists(x => x.FileName == FIRMWARE_FPGA1_FILE_NAME)) - { - throw new IOException($"Invalid firmware upgrade package. file {FIRMWARE_FPGA1_FILE_NAME} could not be found."); - } + upgradeHandler.Total = zip.Entries.Sum(x => x.UncompressedSize); - if (!zip.Entries.ToList().Exists(x => x.FileName == FIRMWARE_FPGA2_FILE_NAME)) - { - throw new IOException($"Invalid firmware upgrade package. file {FIRMWARE_FPGA2_FILE_NAME} could not be found."); - } - - if (!zip.Entries.ToList().Exists(x => x.FileName == FIRMWARE_FPGA3_FILE_NAME)) - { - throw new IOException($"Invalid firmware upgrade package. file {FIRMWARE_FPGA3_FILE_NAME} could not be found."); - } + var storage = CreateStorageManager(); + var drive = await storage.GetStorageDrive(); + var root = await storage.GetRootFolder(); + var existing_folder = root.Items.SingleOrDefault(x => x.Name == FIRMWARE_UPGRADE_FOLDER_NAME); + if (existing_folder != null) + { + await storage.DeleteItem(existing_folder); + } - upgradeHandler.Total = zip.Entries.Sum(x => x.UncompressedSize); + String package_folder = Path.Combine(drive.Root, FIRMWARE_UPGRADE_FOLDER_NAME); - var storage = CreateStorageManager(); - var drive = await storage.GetStorageDrive(); - var root = await storage.GetRootFolder(); - var existing_folder = root.Items.SingleOrDefault(x => x.Name == FIRMWARE_UPGRADE_FOLDER_NAME); - if (existing_folder != null) - { - await storage.DeleteItem(existing_folder); - } + await storage.CreateFolder(package_folder); - String package_folder = Path.Combine(drive.Root, FIRMWARE_UPGRADE_FOLDER_NAME); + List handlers = new List(); + List entries = zip.Entries.ToList(); + List streams = new List(); - await storage.CreateFolder(package_folder); + Action uploadNext = null; + Action validate = null; + Action activate = null; + Action postActivation = null; - List handlers = new List(); - List entries = zip.Entries.ToList(); - List streams = new List(); + uploadNext = new Action(() => + { + if (entries.Count > 0) + { + try + { + var entry = entries.First(); + entries.Remove(entry); + + var reader = entry.OpenReader(); + streams.Add(reader); + + var handler = storage.UploadFile(Path.Combine(package_folder, entry.FileName), reader).Result; + handlers.Add(handler); + handler.Canceled += (_, __) => { upgradeHandler.RaiseCanceled(); cancel = true; }; + handler.Completed += (_, __) => uploadNext(); + handler.Failed += (_, failedEx) => { upgradeHandler.RaiseFailed(failedEx); cancel = true; }; + handler.Progress += (_, e) => + { + if (cancel) + { + handler.Cancel(); + return; + } - Action uploadNext = null; - Action validate = null; - Action activate = null; - Action postActivation = null; + upgradeHandler.RaiseProgress(upgradeHandler.Current + e.Delta, FirmwareUpgradeStatus.Uploading, $"Uploading '{entry.FileName}'..."); + }; + } + catch (Exception ex) + { + upgradeHandler.RaiseFailed(ex); + } + } + else + { + validate(); + } + }); - uploadNext = new Action(() => - { - if (entries.Count > 0) + validate = new Action(() => { try { - var entry = entries.First(); - entries.Remove(entry); - - var reader = entry.OpenReader(); - streams.Add(reader); - - var handler = storage.UploadFile(Path.Combine(package_folder, entry.FileName), reader).Result; - handlers.Add(handler); - handler.Canceled += (_, __) => { upgradeHandler.RaiseCanceled(); cancel = true; }; - handler.Completed += (_, __) => uploadNext(); - handler.Failed += (_, failedEx) => { upgradeHandler.RaiseFailed(failedEx); cancel = true; }; - handler.Progress += (_, e) => - { - if (cancel) - { - handler.Cancel(); - return; - } + streams.ForEach(x => x.Dispose()); + upgradeHandler.RaiseProgress(upgradeHandler.Total, FirmwareUpgradeStatus.Validating, "Validating version..."); + var validateRequest = new ValidateVersionRequest(); + validateRequest.Path = package_folder; + var validateResponse = SendRequest(validateRequest, TimeSpan.FromSeconds(10)).Result; + activate(); + } + catch (Exception ex) + { + upgradeHandler.RaiseFailed(ex); + } + }); - switch (entry.FileName) - { - case FIRMWARE_MCU_FILE_NAME: - upgradeHandler.RaiseProgress(upgradeHandler.Current + e.Delta, FirmwareUpgradeStatus.UploadingMCU); - break; - case FIRMWARE_FPGA1_FILE_NAME: - upgradeHandler.RaiseProgress(upgradeHandler.Current + e.Delta, FirmwareUpgradeStatus.UploadingFPGA1); - break; - case FIRMWARE_FPGA2_FILE_NAME: - upgradeHandler.RaiseProgress(upgradeHandler.Current + e.Delta, FirmwareUpgradeStatus.UploadingFPGA2); - break; - case FIRMWARE_FPGA3_FILE_NAME: - upgradeHandler.RaiseProgress(upgradeHandler.Current + e.Delta, FirmwareUpgradeStatus.UploadingFPGA3); - break; - } - }; + activate = new Action(() => + { + try + { + upgradeHandler.RaiseProgress(upgradeHandler.Total, FirmwareUpgradeStatus.Activating, "Activating version..."); + var activateRequest = new ActivateVersionRequest(); + activateRequest.Path = package_folder; + var activateResponse = SendRequest(activateRequest, TimeSpan.FromSeconds(10)).Result; + postActivation(); } catch (Exception ex) { upgradeHandler.RaiseFailed(ex); } - } - else + }); + + postActivation = new Action(() => { - validate(); - } - }); + upgradeHandler.RaiseCompleted(); + }); - List descriptors = new List(); - descriptors.Add(new VersionFileDescriptor() - { - FileName = Path.Combine(package_folder, FIRMWARE_MCU_FILE_NAME), - Destination = VersionFileDestination.Mcu, - }); - descriptors.Add(new VersionFileDescriptor() - { - FileName = Path.Combine(package_folder, FIRMWARE_FPGA1_FILE_NAME), - Destination = VersionFileDestination.Fpga1, - }); - descriptors.Add(new VersionFileDescriptor() - { - FileName = Path.Combine(package_folder, FIRMWARE_FPGA2_FILE_NAME), - Destination = VersionFileDestination.Fpga2, - }); - descriptors.Add(new VersionFileDescriptor() - { - FileName = Path.Combine(package_folder, FIRMWARE_FPGA3_FILE_NAME), - Destination = VersionFileDestination.Fpga3, - }); + ThreadFactory.StartNew(() => + { + uploadNext(); + }); - validate = new Action(() => + return upgradeHandler; + } + catch (Exception) { - try - { - streams.ForEach(x => x.Dispose()); - upgradeHandler.RaiseProgress(upgradeHandler.Total, FirmwareUpgradeStatus.Validating); - var validateRequest = new ValidateVersionRequest(); - validateRequest.FileDescriptors.AddRange(descriptors); - var validateResponse = SendRequest(validateRequest, TimeSpan.FromSeconds(10)).Result; - activate(); - } - catch (Exception ex) + if (zip != null) { - upgradeHandler.RaiseFailed(ex); + zip.Dispose(); } - }); - activate = new Action(() => + throw; + } + } + + /// + /// Validates the firmware package integrity. + /// + /// The TFP (Tango Firmware Package File) stream. + /// + public Task GetFirmwarePackageInfo(Stream tfpStream) + { + return Task.Factory.StartNew(() => { - try - { - upgradeHandler.RaiseProgress(upgradeHandler.Total, FirmwareUpgradeStatus.Activating); - var activateRequest = new ActivateVersionRequest(); - activateRequest.FileDescriptors.AddRange(descriptors); - var activateResponse = SendRequest(activateRequest, TimeSpan.FromSeconds(10)).Result; - postActivation(); - } - catch (Exception ex) + using (ZipFile zip = ZipFile.Read(tfpStream)) { - upgradeHandler.RaiseFailed(ex); + var reader = zip.Entries.SingleOrDefault(x => x.FileName == FIRMWARE_UPGRADE_CONFIG_FILE_NAME).OpenReader(); + var info = VersionPackageDescriptor.Parser.ParseFrom(reader); + reader.Close(); + reader.Dispose(); + return info; } }); + } - postActivation = new Action(() => - { - upgradeHandler.RaiseCompleted(); - }); - - ThreadFactory.StartNew(() => - { - uploadNext(); - }); + /// + /// Directs the embedded device to validate the last uploaded firmware package. + /// + /// + public async Task ValidateFirmwareVersion(String path) + { + var validateRequest = new ValidateVersionRequest(); + validateRequest.Path = path; + await SendRequest(validateRequest, TimeSpan.FromSeconds(10)); + } - return upgradeHandler; + /// + /// Directs the embedded device to validate the last uploaded firmware package. + /// + /// + public async Task ActivateFirmwareVersion(String path) + { + var activateRequest = new ActivateVersionRequest(); + activateRequest.Path = path; + await SendRequest(activateRequest, TimeSpan.FromSeconds(10)); } #endregion diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs index 0743fe54d..1a82d0ff4 100644 --- a/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageManager.cs @@ -312,6 +312,7 @@ namespace Tango.Integration.Storage return; } + byte[] buffer = chunk_response.Message.Buffer.ToByteArray(); stream.Write(buffer, 0, buffer.Length); diff --git a/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj b/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj index 14cdc03c5..b4e104f4d 100644 --- a/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj +++ b/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj @@ -89,9 +89,9 @@ - - - + + + diff --git a/Software/Visual_Studio/Tango.Integration/Upgrade/FirmwareUpgradeHandler.cs b/Software/Visual_Studio/Tango.Integration/Upgrade/FirmwareUpgradeHandler.cs new file mode 100644 index 000000000..774824b49 --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/Upgrade/FirmwareUpgradeHandler.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Integration.Storage; + +namespace Tango.Integration.Upgrade +{ + public class FirmwareUpgradeHandler : ExtendedObject + { + private Action _cancelAction; + + public event EventHandler Progress; + public event EventHandler Completed; + public event EventHandler Canceled; + public event EventHandler Failed; + + internal FirmwareUpgradeHandler() + { + Message = "Initializing..."; + } + + internal FirmwareUpgradeHandler(Action cancelAction) : this() + { + _cancelAction = cancelAction; + } + + private String _message; + public String Message + { + get { return _message; } + set { _message = value; RaisePropertyChangedAuto(); } + } + + private FirmwareUpgradeStatus _status; + public FirmwareUpgradeStatus Status + { + get { return _status; } + private set { _status = value; RaisePropertyChangedAuto(); } + } + + private long _current; + public long Current + { + get { return _current; } + internal set + { + _current = value; RaisePropertyChangedAuto(); + } + } + + private long _total; + public long Total + { + get { return _total; } + internal set { _total = value; RaisePropertyChangedAuto(); } + } + + public Task Cancel() + { + return Task.Factory.StartNew(() => + { + _cancelAction.Invoke(); + Message = "Canceled."; + Status = FirmwareUpgradeStatus.Canceled; + Canceled?.Invoke(this, new EventArgs()); + }); + } + + internal void RaiseCompleted() + { + Status = FirmwareUpgradeStatus.Completed; + Message = "Completed."; + Completed?.Invoke(this, new EventArgs()); + } + + internal void RaiseCanceled() + { + Status = FirmwareUpgradeStatus.Canceled; + Message = "Canceled."; + Canceled?.Invoke(this, new EventArgs()); + } + + internal void RaiseFailed(Exception ex) + { + Status = FirmwareUpgradeStatus.Failed; + Message = "Failed."; + Failed?.Invoke(this, ex); + } + + internal void RaiseProgress(long current, FirmwareUpgradeStatus status, String message) + { + Current = current; + Status = status; + Message = message; + + Progress?.Invoke(this, new FirmwareUpgradeProgressEventArgs() + { + Current = Current, + Status = Status, + Total = Total, + Message = Message, + }); + } + } +} diff --git a/Software/Visual_Studio/Tango.Integration/Upgrade/FirmwareUpgradeProgressEventArgs.cs b/Software/Visual_Studio/Tango.Integration/Upgrade/FirmwareUpgradeProgressEventArgs.cs new file mode 100644 index 000000000..fa4f4cc96 --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/Upgrade/FirmwareUpgradeProgressEventArgs.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Integration.Upgrade +{ + public class FirmwareUpgradeProgressEventArgs : EventArgs + { + public long Current { get; set; } + public long Total { get; set; } + public FirmwareUpgradeStatus Status { get; set; } + public String Message { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.Integration/Upgrade/FirmwareUpgradeStatus.cs b/Software/Visual_Studio/Tango.Integration/Upgrade/FirmwareUpgradeStatus.cs new file mode 100644 index 000000000..0d8449ee9 --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/Upgrade/FirmwareUpgradeStatus.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Integration.Upgrade +{ + public enum FirmwareUpgradeStatus + { + [Description("Initializing...")] + Initializing, + [Description("Uploading files...")] + Uploading, + [Description("Validating version...")] + Validating, + [Description("Activating version...")] + Activating, + [Description("Waiting for device reboot...")] + WaitingForReboot, + [Description("Connecting...")] + Connecting, + [Description("Completed")] + Completed, + [Description("Aborted")] + Canceled, + [Description("Failed")] + Failed, + } +} diff --git a/Software/Visual_Studio/Tango.PMR/IO/ActivateVersionRequest.cs b/Software/Visual_Studio/Tango.PMR/IO/ActivateVersionRequest.cs index b20f28d63..0901521e8 100644 --- a/Software/Visual_Studio/Tango.PMR/IO/ActivateVersionRequest.cs +++ b/Software/Visual_Studio/Tango.PMR/IO/ActivateVersionRequest.cs @@ -22,15 +22,13 @@ namespace Tango.PMR.IO { static ActivateVersionRequestReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "ChxBY3RpdmF0ZVZlcnNpb25SZXF1ZXN0LnByb3RvEgxUYW5nby5QTVIuSU8a", - "G1ZlcnNpb25GaWxlRGVzY3JpcHRvci5wcm90byJWChZBY3RpdmF0ZVZlcnNp", - "b25SZXF1ZXN0EjwKD0ZpbGVEZXNjcmlwdG9ycxgBIAMoCzIjLlRhbmdvLlBN", - "Ui5JTy5WZXJzaW9uRmlsZURlc2NyaXB0b3JCGAoWY29tLnR3aW5lLnRhbmdv", - "LnBtci5pb2IGcHJvdG8z")); + "ChxBY3RpdmF0ZVZlcnNpb25SZXF1ZXN0LnByb3RvEgxUYW5nby5QTVIuSU8i", + "JgoWQWN0aXZhdGVWZXJzaW9uUmVxdWVzdBIMCgRQYXRoGAEgASgJQhgKFmNv", + "bS50d2luZS50YW5nby5wbXIuaW9iBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, - new pbr::FileDescriptor[] { global::Tango.PMR.IO.VersionFileDescriptorReflection.Descriptor, }, + new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.IO.ActivateVersionRequest), global::Tango.PMR.IO.ActivateVersionRequest.Parser, new[]{ "FileDescriptors" }, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.IO.ActivateVersionRequest), global::Tango.PMR.IO.ActivateVersionRequest.Parser, new[]{ "Path" }, null, null, null) })); } #endregion @@ -61,7 +59,7 @@ namespace Tango.PMR.IO { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ActivateVersionRequest(ActivateVersionRequest other) : this() { - fileDescriptors_ = other.fileDescriptors_.Clone(); + path_ = other.path_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -69,14 +67,15 @@ namespace Tango.PMR.IO { return new ActivateVersionRequest(this); } - /// Field number for the "FileDescriptors" field. - public const int FileDescriptorsFieldNumber = 1; - private static readonly pb::FieldCodec _repeated_fileDescriptors_codec - = pb::FieldCodec.ForMessage(10, global::Tango.PMR.IO.VersionFileDescriptor.Parser); - private readonly pbc::RepeatedField fileDescriptors_ = new pbc::RepeatedField(); + /// Field number for the "Path" field. + public const int PathFieldNumber = 1; + private string path_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField FileDescriptors { - get { return fileDescriptors_; } + public string Path { + get { return path_; } + set { + path_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -92,14 +91,14 @@ namespace Tango.PMR.IO { if (ReferenceEquals(other, this)) { return true; } - if(!fileDescriptors_.Equals(other.fileDescriptors_)) return false; + if (Path != other.Path) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - hash ^= fileDescriptors_.GetHashCode(); + if (Path.Length != 0) hash ^= Path.GetHashCode(); return hash; } @@ -110,13 +109,18 @@ namespace Tango.PMR.IO { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - fileDescriptors_.WriteTo(output, _repeated_fileDescriptors_codec); + if (Path.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Path); + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - size += fileDescriptors_.CalculateSize(_repeated_fileDescriptors_codec); + if (Path.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Path); + } return size; } @@ -125,7 +129,9 @@ namespace Tango.PMR.IO { if (other == null) { return; } - fileDescriptors_.Add(other.fileDescriptors_); + if (other.Path.Length != 0) { + Path = other.Path; + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -137,7 +143,7 @@ namespace Tango.PMR.IO { input.SkipLastField(); break; case 10: { - fileDescriptors_.AddEntriesFrom(input, _repeated_fileDescriptors_codec); + Path = input.ReadString(); break; } } diff --git a/Software/Visual_Studio/Tango.PMR/IO/ValidateVersionRequest.cs b/Software/Visual_Studio/Tango.PMR/IO/ValidateVersionRequest.cs index 0dda007d2..d5d032969 100644 --- a/Software/Visual_Studio/Tango.PMR/IO/ValidateVersionRequest.cs +++ b/Software/Visual_Studio/Tango.PMR/IO/ValidateVersionRequest.cs @@ -22,15 +22,13 @@ namespace Tango.PMR.IO { static ValidateVersionRequestReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "ChxWYWxpZGF0ZVZlcnNpb25SZXF1ZXN0LnByb3RvEgxUYW5nby5QTVIuSU8a", - "G1ZlcnNpb25GaWxlRGVzY3JpcHRvci5wcm90byJWChZWYWxpZGF0ZVZlcnNp", - "b25SZXF1ZXN0EjwKD0ZpbGVEZXNjcmlwdG9ycxgBIAMoCzIjLlRhbmdvLlBN", - "Ui5JTy5WZXJzaW9uRmlsZURlc2NyaXB0b3JCGAoWY29tLnR3aW5lLnRhbmdv", - "LnBtci5pb2IGcHJvdG8z")); + "ChxWYWxpZGF0ZVZlcnNpb25SZXF1ZXN0LnByb3RvEgxUYW5nby5QTVIuSU8i", + "JgoWVmFsaWRhdGVWZXJzaW9uUmVxdWVzdBIMCgRQYXRoGAEgASgJQhgKFmNv", + "bS50d2luZS50YW5nby5wbXIuaW9iBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, - new pbr::FileDescriptor[] { global::Tango.PMR.IO.VersionFileDescriptorReflection.Descriptor, }, + new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.IO.ValidateVersionRequest), global::Tango.PMR.IO.ValidateVersionRequest.Parser, new[]{ "FileDescriptors" }, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.IO.ValidateVersionRequest), global::Tango.PMR.IO.ValidateVersionRequest.Parser, new[]{ "Path" }, null, null, null) })); } #endregion @@ -61,7 +59,7 @@ namespace Tango.PMR.IO { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ValidateVersionRequest(ValidateVersionRequest other) : this() { - fileDescriptors_ = other.fileDescriptors_.Clone(); + path_ = other.path_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -69,14 +67,15 @@ namespace Tango.PMR.IO { return new ValidateVersionRequest(this); } - /// Field number for the "FileDescriptors" field. - public const int FileDescriptorsFieldNumber = 1; - private static readonly pb::FieldCodec _repeated_fileDescriptors_codec - = pb::FieldCodec.ForMessage(10, global::Tango.PMR.IO.VersionFileDescriptor.Parser); - private readonly pbc::RepeatedField fileDescriptors_ = new pbc::RepeatedField(); + /// Field number for the "Path" field. + public const int PathFieldNumber = 1; + private string path_ = ""; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pbc::RepeatedField FileDescriptors { - get { return fileDescriptors_; } + public string Path { + get { return path_; } + set { + path_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -92,14 +91,14 @@ namespace Tango.PMR.IO { if (ReferenceEquals(other, this)) { return true; } - if(!fileDescriptors_.Equals(other.fileDescriptors_)) return false; + if (Path != other.Path) return false; return true; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() { int hash = 1; - hash ^= fileDescriptors_.GetHashCode(); + if (Path.Length != 0) hash ^= Path.GetHashCode(); return hash; } @@ -110,13 +109,18 @@ namespace Tango.PMR.IO { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { - fileDescriptors_.WriteTo(output, _repeated_fileDescriptors_codec); + if (Path.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Path); + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; - size += fileDescriptors_.CalculateSize(_repeated_fileDescriptors_codec); + if (Path.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Path); + } return size; } @@ -125,7 +129,9 @@ namespace Tango.PMR.IO { if (other == null) { return; } - fileDescriptors_.Add(other.fileDescriptors_); + if (other.Path.Length != 0) { + Path = other.Path; + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -137,7 +143,7 @@ namespace Tango.PMR.IO { input.SkipLastField(); break; case 10: { - fileDescriptors_.AddEntriesFrom(input, _repeated_fileDescriptors_codec); + Path = input.ReadString(); break; } } diff --git a/Software/Visual_Studio/Tango.PMR/IO/VersionPackageDescriptor.cs b/Software/Visual_Studio/Tango.PMR/IO/VersionPackageDescriptor.cs new file mode 100644 index 000000000..54c9e0e9d --- /dev/null +++ b/Software/Visual_Studio/Tango.PMR/IO/VersionPackageDescriptor.cs @@ -0,0 +1,153 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: VersionPackageDescriptor.proto +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Tango.PMR.IO { + + /// Holder for reflection information generated from VersionPackageDescriptor.proto + public static partial class VersionPackageDescriptorReflection { + + #region Descriptor + /// File descriptor for VersionPackageDescriptor.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static VersionPackageDescriptorReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Ch5WZXJzaW9uUGFja2FnZURlc2NyaXB0b3IucHJvdG8SDFRhbmdvLlBNUi5J", + "TxobVmVyc2lvbkZpbGVEZXNjcmlwdG9yLnByb3RvIlgKGFZlcnNpb25QYWNr", + "YWdlRGVzY3JpcHRvchI8Cg9GaWxlRGVzY3JpcHRvcnMYASADKAsyIy5UYW5n", + "by5QTVIuSU8uVmVyc2lvbkZpbGVEZXNjcmlwdG9yQhgKFmNvbS50d2luZS50", + "YW5nby5wbXIuaW9iBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Tango.PMR.IO.VersionFileDescriptorReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.IO.VersionPackageDescriptor), global::Tango.PMR.IO.VersionPackageDescriptor.Parser, new[]{ "FileDescriptors" }, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class VersionPackageDescriptor : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new VersionPackageDescriptor()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Tango.PMR.IO.VersionPackageDescriptorReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public VersionPackageDescriptor() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public VersionPackageDescriptor(VersionPackageDescriptor other) : this() { + fileDescriptors_ = other.fileDescriptors_.Clone(); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public VersionPackageDescriptor Clone() { + return new VersionPackageDescriptor(this); + } + + /// Field number for the "FileDescriptors" field. + public const int FileDescriptorsFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_fileDescriptors_codec + = pb::FieldCodec.ForMessage(10, global::Tango.PMR.IO.VersionFileDescriptor.Parser); + private readonly pbc::RepeatedField fileDescriptors_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField FileDescriptors { + get { return fileDescriptors_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as VersionPackageDescriptor); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(VersionPackageDescriptor other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!fileDescriptors_.Equals(other.fileDescriptors_)) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= fileDescriptors_.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + fileDescriptors_.WriteTo(output, _repeated_fileDescriptors_codec); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += fileDescriptors_.CalculateSize(_repeated_fileDescriptors_codec); + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(VersionPackageDescriptor other) { + if (other == null) { + return; + } + fileDescriptors_.Add(other.fileDescriptors_); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + fileDescriptors_.AddEntriesFrom(input, _repeated_fileDescriptors_codec); + break; + } + } + } + } + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj b/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj index bbea736e5..2fc510b58 100644 --- a/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj +++ b/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj @@ -199,6 +199,7 @@ + @@ -258,7 +259,7 @@ - + \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Transport/TransporterBase.cs b/Software/Visual_Studio/Tango.Transport/TransporterBase.cs index 195ff845f..ed57e5014 100644 --- a/Software/Visual_Studio/Tango.Transport/TransporterBase.cs +++ b/Software/Visual_Studio/Tango.Transport/TransporterBase.cs @@ -28,7 +28,7 @@ namespace Tango.Transport { private const int MESSAGE_TOKEN_LENGTH = 36; private ProducerConsumerQueue _sendingQueue; - private List _pendingRequests; + private ConcurrentList _pendingRequests; private ProducerConsumerQueue _arrivedResponses; private Thread _pushThread; private Thread _pullThread; @@ -260,7 +260,7 @@ namespace Tango.Transport Encoder = new ProtoEncoder(); _pendingResponses = new Dictionary(); _sendingQueue = new ProducerConsumerQueue(); - _pendingRequests = new List(); + _pendingRequests = new ConcurrentList(); _arrivedResponses = new ProducerConsumerQueue(); RequestTimeout = TimeSpan.FromSeconds(5); } @@ -284,7 +284,7 @@ namespace Tango.Transport public void ClearQueues() { _sendingQueue = new ProducerConsumerQueue(); - _pendingRequests = new List(); + _pendingRequests = new ConcurrentList(); _arrivedResponses = new ProducerConsumerQueue(); } @@ -343,7 +343,7 @@ namespace Tango.Transport TransportMessage message = new TransportMessage(container.Token, request, TransportMessageDirection.Request, () => container.ToByteArray(), source); EnqueueMessageOut(message); - TimeoutTask.StartNew(() => + TimeoutTask.StartNew(() => { if (!source.Task.IsCompleted) @@ -413,7 +413,7 @@ namespace Tango.Transport TransportMessage message = new TransportMessage(container.Token, container, TransportMessageDirection.Request, () => container.ToByteArray(), source); EnqueueMessageOut(message); - TimeoutTask.StartNew(() => + TimeoutTask.StartNew(() => { if (!source.Task.IsCompleted) @@ -503,7 +503,7 @@ namespace Tango.Transport }; EnqueueMessageOut(message); - TimeoutTask.StartNew(() => + TimeoutTask.StartNew(() => { if (!message.AtLeastOneResponseReceived) @@ -538,7 +538,7 @@ namespace Tango.Transport TransportMessage> message = new TransportMessage>(request.Container.Token, request, TransportMessageDirection.Request, () => Encoder.Encode(request), source); EnqueueMessageOut(message); - TimeoutTask.StartNew(() => + TimeoutTask.StartNew(() => { if (!source.Task.IsCompleted) @@ -583,7 +583,7 @@ namespace Tango.Transport }; EnqueueMessageOut(message); - TimeoutTask.StartNew(() => + TimeoutTask.StartNew(() => { if (!message.AtLeastOneResponseReceived) @@ -649,7 +649,7 @@ namespace Tango.Transport }; EnqueueMessageOut(message); - TimeoutTask.StartNew(() => + TimeoutTask.StartNew(() => { if (!message.AtLeastOneResponseReceived) @@ -878,7 +878,10 @@ namespace Tango.Transport if (message.Direction == TransportMessageDirection.Request) { - _pendingRequests.Add(message); + lock (_pendingRequests) + { + _pendingRequests.Add(message); + } } else { @@ -930,7 +933,11 @@ namespace Tango.Transport LogManager.Log("Searching for pending request token: " + container.Token, LogCategory.Debug); - TransportMessageBase request = _pendingRequests.ToList().SingleOrDefault(x => x.Token == container.Token); + TransportMessageBase request = null; + lock (_pendingRequests) + { + request = _pendingRequests.ToList().SingleOrDefault(x => x.Token == container.Token); + } if (request != null) { diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln index 910b4d1ea..ed2c4676e 100644 --- a/Software/Visual_Studio/Tango.sln +++ b/Software/Visual_Studio/Tango.sln @@ -240,6 +240,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.PPC.Events", "PPC\Mod EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.MachineStudio.Storage", "MachineStudio\Modules\Tango.MachineStudio.Storage\Tango.MachineStudio.Storage.csproj", "{5991F6B5-EA4E-41E9-A4F6-7D3A50010FD6}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.FirmwarePackageGenerator", "Utilities\Tango.FirmwarePackageGenerator\Tango.FirmwarePackageGenerator.csproj", "{43135FB9-41DB-4F87-9771-CF2C762027C0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AppVeyor|Any CPU = AppVeyor|Any CPU @@ -4283,6 +4285,46 @@ Global {5991F6B5-EA4E-41E9-A4F6-7D3A50010FD6}.Release|x64.Build.0 = Release|Any CPU {5991F6B5-EA4E-41E9-A4F6-7D3A50010FD6}.Release|x86.ActiveCfg = Release|Any CPU {5991F6B5-EA4E-41E9-A4F6-7D3A50010FD6}.Release|x86.Build.0 = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.AppVeyor|Any CPU.ActiveCfg = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.AppVeyor|Any CPU.Build.0 = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.AppVeyor|ARM.ActiveCfg = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.AppVeyor|ARM.Build.0 = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.AppVeyor|ARM64.ActiveCfg = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.AppVeyor|ARM64.Build.0 = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.AppVeyor|x64.ActiveCfg = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.AppVeyor|x64.Build.0 = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.AppVeyor|x86.ActiveCfg = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.AppVeyor|x86.Build.0 = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Debug|ARM.ActiveCfg = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Debug|ARM.Build.0 = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Debug|ARM64.Build.0 = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Debug|x64.ActiveCfg = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Debug|x64.Build.0 = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Debug|x86.ActiveCfg = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Debug|x86.Build.0 = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.DefaultBuild|Any CPU.ActiveCfg = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.DefaultBuild|Any CPU.Build.0 = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.DefaultBuild|ARM.ActiveCfg = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.DefaultBuild|ARM.Build.0 = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.DefaultBuild|ARM64.ActiveCfg = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.DefaultBuild|ARM64.Build.0 = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.DefaultBuild|x64.ActiveCfg = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.DefaultBuild|x64.Build.0 = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.DefaultBuild|x86.ActiveCfg = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.DefaultBuild|x86.Build.0 = Debug|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Release|Any CPU.Build.0 = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Release|ARM.ActiveCfg = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Release|ARM.Build.0 = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Release|ARM64.ActiveCfg = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Release|ARM64.Build.0 = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Release|x64.ActiveCfg = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Release|x64.Build.0 = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Release|x86.ActiveCfg = Release|Any CPU + {43135FB9-41DB-4F87-9771-CF2C762027C0}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -4357,14 +4399,15 @@ Global {04FEBB02-F782-4B96-B47D-F6902AFA43BE} = {0048447D-1D94-4E60-9DAD-7349C777CB4E} {A8077B3E-8DD6-4572-8EC4-A27BDC91B70A} = {0048447D-1D94-4E60-9DAD-7349C777CB4E} {5991F6B5-EA4E-41E9-A4F6-7D3A50010FD6} = {B2AF4F3F-2828-47C3-8F3E-A0EA0BD66FF8} + {43135FB9-41DB-4F87-9771-CF2C762027C0} = {5F6BBAA8-EAD0-4B18-97E5-55B4F56DD760} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {7986F7F4-A86A-4994-B1B6-0988D7F057B6} - BuildVersion_BuildVersioningStyle = None.None.Increment.DeltaBaseYearDayOfYear - BuildVersion_UpdateAssemblyVersion = True - BuildVersion_UpdateFileVersion = False - BuildVersion_StartDate = 2000/1/1 - BuildVersion_AssemblyInfoFilename = Properties\AssemblyInfo.cs BuildVersion_UseGlobalSettings = False + BuildVersion_AssemblyInfoFilename = Properties\AssemblyInfo.cs + BuildVersion_StartDate = 2000/1/1 + BuildVersion_UpdateFileVersion = False + BuildVersion_UpdateAssemblyVersion = True + BuildVersion_BuildVersioningStyle = None.None.Increment.DeltaBaseYearDayOfYear + SolutionGuid = {7986F7F4-A86A-4994-B1B6-0988D7F057B6} EndGlobalSection EndGlobal diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/App.config b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/App.config new file mode 100644 index 000000000..be3d2b956 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/App.config @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/App.xaml b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/App.xaml new file mode 100644 index 000000000..acec406cb --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/App.xaml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/App.xaml.cs b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/App.xaml.cs new file mode 100644 index 000000000..39bd940b8 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace Tango.FirmwarePackageGenerator +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Images/firmware_upgrade.png b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Images/firmware_upgrade.png new file mode 100644 index 000000000..fc0799143 Binary files /dev/null and b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Images/firmware_upgrade.png differ diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/MainWindow.xaml b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/MainWindow.xaml new file mode 100644 index 000000000..76b6f8aa4 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/MainWindow.xaml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + Fill the grid below to add firmware version files. + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/MainWindow.xaml.cs b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/MainWindow.xaml.cs new file mode 100644 index 000000000..9aa79f469 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/MainWindow.xaml.cs @@ -0,0 +1,43 @@ +using MahApps.Metro.Controls; +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Linq; +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.Navigation; +using System.Windows.Shapes; + +namespace Tango.FirmwarePackageGenerator +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : MetroWindow + { + public MainWindow() + { + InitializeComponent(); + DataContext = new MainWindowVM(); + } + + private void DataGrid_AddingNewItem(object sender, AddingNewItemEventArgs e) + { + OpenFileDialog dlg = new OpenFileDialog(); + dlg.Filter = "Firmware Package Files|*.bin;*.fpga"; + if (dlg.ShowDialog().Value) + { + VersionFileModel item = new VersionFileModel(); + item.Path = dlg.FileName; + e.NewItem = item; + } + } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/MainWindowVM.cs b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/MainWindowVM.cs new file mode 100644 index 000000000..718aa3aac --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/MainWindowVM.cs @@ -0,0 +1,103 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.Commands; +using Tango.PMR.IO; +using Tango.SharedUI; +using Google.Protobuf; +using Ionic.Zip; +using System.Windows; + +namespace Tango.FirmwarePackageGenerator +{ + public class MainWindowVM : ViewModel + { + private ObservableCollection _versionFiles; + public ObservableCollection VersionFiles + { + get { return _versionFiles; } + set { _versionFiles = value; RaisePropertyChangedAuto(); } + } + + public RelayCommand GenerateCommand { get; set; } + + public MainWindowVM() + { + VersionFiles = new ObservableCollection(); + GenerateCommand = new RelayCommand(Generate); + } + + private void Generate() + { + SaveFileDialog dlg = new SaveFileDialog(); + dlg.Title = "Save Firmware Package File"; + dlg.Filter = "Tango Firmware Package|*.tfp"; + dlg.DefaultExt = ".tfp"; + dlg.FileName = "firmware_package.tfp"; + if (dlg.ShowDialog().Value) + { + try + { + VersionPackageDescriptor descriptor = new VersionPackageDescriptor(); + foreach (var item in VersionFiles) + { + descriptor.FileDescriptors.Add(new VersionFileDescriptor() + { + Destination = item.Destination, + FileName = item.FileName, + Version = item.Version, + }); + } + + using (MemoryStream ms = new MemoryStream()) + { + descriptor.WriteTo(ms); + + using (var zip = new ZipFile()) + { + zip.AddEntry("package.cfg", ms.ToArray()); + foreach (var item in VersionFiles) + { + zip.AddFile(item.Path, "/"); + } + + zip.Save(dlg.FileName); + } + } + + //Validate + using (ZipFile zip = ZipFile.Read(dlg.FileName)) + { + var reader = zip.Entries.SingleOrDefault(x => x.FileName == "package.cfg").OpenReader(); + var descriptor2 = VersionPackageDescriptor.Parser.ParseFrom(reader); + if (descriptor.ToString() != descriptor2.ToString()) + { + throw new IOException("The generated package does not match the source package."); + } + } + + ShowInfo("Package generated successfully."); + } + catch (Exception ex) + { + ShowError($"Error while trying to generate the package.\n{ex.Message}"); + } + } + } + + private void ShowError(String error) + { + MessageBox.Show(error, "PPC Publisher", MessageBoxButton.OK, MessageBoxImage.Error); + } + + private void ShowInfo(String message) + { + MessageBox.Show(message, "PPC Publisher", MessageBoxButton.OK, MessageBoxImage.Information); + } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..b9727e630 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Tango - Firmware Package Generator Utility")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: ComVisible(false)] \ No newline at end of file diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Resources.Designer.cs b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Resources.Designer.cs new file mode 100644 index 000000000..30d0ee544 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Tango.FirmwarePackageGenerator.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Tango.FirmwarePackageGenerator.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Resources.resx b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Settings.Designer.cs b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Settings.Designer.cs new file mode 100644 index 000000000..c3d44ce2c --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Tango.FirmwarePackageGenerator.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Settings.settings b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Settings.settings new file mode 100644 index 000000000..033d7a5e9 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Tango.FirmwarePackageGenerator.csproj b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Tango.FirmwarePackageGenerator.csproj new file mode 100644 index 000000000..4ca1eb322 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/Tango.FirmwarePackageGenerator.csproj @@ -0,0 +1,134 @@ + + + + + Debug + AnyCPU + {43135FB9-41DB-4F87-9771-CF2C762027C0} + WinExe + Tango.FirmwarePackageGenerator + fpgen + v4.6.1 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + true + + + AnyCPU + true + full + false + ..\..\Build\Utilities\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + ..\..\Build\Utilities\Debug\ + TRACE + prompt + 4 + + + + ..\..\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.5.0\lib\net45\MahApps.Metro.dll + + + + + ..\..\packages\MahApps.Metro.1.5.0\lib\net45\System.Windows.Interactivity.dll + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + + MSBuild:Compile + Designer + + + GlobalVersionInfo.cs + + + App.xaml + Code + + + MainWindow.xaml + Code + + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + {a34ee0f0-649d-41c8-8489-b6f1cc6924ee} + Tango.Core + + + {e4927038-348d-4295-aaf4-861c58cb3943} + Tango.PMR + + + {8491d07b-c1f6-4b62-a412-41b9fd2d6538} + Tango.SharedUI + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/VersionFileModel.cs b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/VersionFileModel.cs new file mode 100644 index 000000000..1431fa74d --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/VersionFileModel.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.PMR.IO; + +namespace Tango.FirmwarePackageGenerator +{ + public class VersionFileModel : ExtendedObject + { + public VersionFileModel() + { + Version = "1.0.0.0"; + } + + private String _path; + public String Path + { + get { return _path; } + set { _path = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(FileName)); } + } + + public String FileName + { + get { return System.IO.Path.GetFileName(Path); } + } + + private String _version; + public String Version + { + get { return _version; } + set { _version = value; RaisePropertyChangedAuto(); } + } + + private VersionFileDestination _destination; + public VersionFileDestination Destination + { + get { return _destination; } + set { _destination = value; RaisePropertyChangedAuto(); } + } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/packages.config b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/packages.config new file mode 100644 index 000000000..5521d9817 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.FirmwarePackageGenerator/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file -- cgit v1.3.1