From f00233f493b38f1a8eb9422f3c9ac4193f264486 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Wed, 20 May 2020 18:22:29 +0300 Subject: Fixed issue with machine virtual user when synchronizing jobs from PPC. --- .../Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'Software/Visual_Studio/Web/Tango.MachineService') diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs index 28acb3647..10af2f725 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs @@ -589,6 +589,7 @@ namespace Tango.MachineService.Controllers { var run = dto.ToObservable(); run.ID = 0; + run.UserGuid = machineUser.Guid; run.IsSynchronized = true; if (db.JobRuns.SingleOrDefault(x => x.Guid == run.Guid) == null) -- cgit v1.3.1 From 7c7aba43ab895d02e0209861550fed3bc12f3904 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Tue, 28 Jul 2020 15:27:05 +0300 Subject: Implemented Tango FSE Publish Utils. Added FSE to AzureUtils on environment upgrade. --- .../Advanced Installer Projects/FSE Installer.aip | 515 ++++++++++++++++++++- .../Controls/WebAppPropertiesControl.xaml | 3 + .../Controls/WebAppPropertiesControl.xaml.cs | 9 + .../Azure/Tango.AzureUtils.UI/MainWindow.xaml | 2 +- .../Views/EnvironmentUpgradeView.xaml | 4 +- .../Tango.AzureUtils/Database/DatabaseManager.cs | 77 ++- .../Environment/EnvironmentManager.cs | 40 ++ .../Environment/EnvironmentSettings.cs | 2 + .../Environment/UpgradeEnvironmentConfiguration.cs | 2 + .../Tango.AzureUtils/MachineServiceSettings.cs | 1 + .../Tango.AzureUtils/Storage/StorageManager.cs | 65 ++- .../FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs | 27 ++ .../FSE/Tango.FSE.Publisher.UI/App.config | 9 + .../FSE/Tango.FSE.Publisher.UI/App.xaml | 9 + .../FSE/Tango.FSE.Publisher.UI/App.xaml.cs | 17 + .../FSE/Tango.FSE.Publisher.UI/MainWindow.xaml | 66 +++ .../FSE/Tango.FSE.Publisher.UI/MainWindow.xaml.cs | 34 ++ .../FSE/Tango.FSE.Publisher.UI/MainWindowVM.cs | 316 +++++++++++++ .../Properties/AssemblyInfo.cs | 55 +++ .../Properties/Resources.Designer.cs | 71 +++ .../Properties/Resources.resx | 117 +++++ .../Properties/Settings.Designer.cs | 30 ++ .../Properties/Settings.settings | 7 + .../Tango.FSE.Publisher.UI/PublisherSettings.cs | 15 + .../Tango.FSE.Publisher.UI.csproj | 141 ++++++ .../FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs | 2 +- .../Tango.FSE.Web/Messages/LatestVersionRequest.cs | 15 + .../Messages/LatestVersionResponse.cs | 15 + .../Messages/UploadCompletedRequest.cs | 15 + .../Messages/UploadCompletedResponse.cs | 14 + .../Tango.FSE.Web/Messages/UploadVersionRequest.cs | 19 + .../Messages/UploadVersionResponse.cs | 19 + .../FSE/Tango.FSE.Web/Tango.FSE.Web.csproj | 6 + Software/Visual_Studio/Tango.sln | 23 + .../Controllers/FSEController.cs | 104 +++++ .../Models/FSEPendingUpload.cs | 22 + .../Tango.MachineService.csproj | 3 +- 37 files changed, 1862 insertions(+), 29 deletions(-) create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/App.config create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/App.xaml create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/App.xaml.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/MainWindow.xaml create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/MainWindow.xaml.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/MainWindowVM.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/AssemblyInfo.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/Resources.Designer.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/Resources.resx create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/Settings.Designer.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/Settings.settings create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/PublisherSettings.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Tango.FSE.Publisher.UI.csproj create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/LatestVersionRequest.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/LatestVersionResponse.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadCompletedRequest.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadCompletedResponse.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadVersionRequest.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadVersionResponse.cs create mode 100644 Software/Visual_Studio/Web/Tango.MachineService/Models/FSEPendingUpload.cs (limited to 'Software/Visual_Studio/Web/Tango.MachineService') diff --git a/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip b/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip index bd71ea0a1..eec051e8e 100644 --- a/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip +++ b/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip @@ -24,10 +24,10 @@ - + - + @@ -51,8 +51,21 @@ + + + + + + + + + + + + + @@ -84,10 +97,14 @@ + + + + @@ -100,19 +117,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -232,6 +379,7 @@ + @@ -272,6 +420,7 @@ + @@ -310,11 +459,13 @@ + + + + - - @@ -636,14 +787,109 @@ + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -651,21 +897,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -677,7 +1014,7 @@ - + @@ -764,8 +1101,6 @@ - - @@ -1069,8 +1404,146 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml index fe8b4bdef..aadfb7918 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml @@ -61,6 +61,9 @@ Tango Firmware Version:: + + Tango FSE Version: + diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml.cs b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml.cs index ea7475fb1..8888dfc02 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml.cs +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml.cs @@ -47,6 +47,14 @@ namespace Tango.AzureUtils.UI.Controls public static readonly DependencyProperty TangoVersionProperty = DependencyProperty.Register("TangoVersion", typeof(TangoVersion), typeof(WebAppPropertiesControl), new PropertyMetadata(null)); + public FseVersion FseVersion + { + get { return (FseVersion)GetValue(FseVersionProperty); } + set { SetValue(FseVersionProperty, value); } + } + public static readonly DependencyProperty FseVersionProperty = + DependencyProperty.Register("FseVersion", typeof(FseVersion), typeof(WebAppPropertiesControl), new PropertyMetadata(null)); + public MachineStudioVersion MachineStudioVersion { get { return (MachineStudioVersion)GetValue(MachineStudioVersionProperty); } @@ -88,6 +96,7 @@ namespace Tango.AzureUtils.UI.Controls var databaseManager = new DatabaseManager(azure); TangoVersion = await databaseManager.GetLatestPPCVersion(app); MachineStudioVersion = await databaseManager.GetLatestMachineStudioVersion(app); + FseVersion = await databaseManager.GetLatestFSEVersion(app); } catch { } finally diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/MainWindow.xaml b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/MainWindow.xaml index 7985f7985..6eaedea2a 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/MainWindow.xaml +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/MainWindow.xaml @@ -6,7 +6,7 @@ xmlns:views="clr-namespace:Tango.AzureUtils.UI.Views" xmlns:local="clr-namespace:Tango.AzureUtils.UI" mc:Ignorable="d" - Title="Azure Utils" Height="900" Width="1280"> + Title="Azure Utils" Height="920" Width="1280"> diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Views/EnvironmentUpgradeView.xaml b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Views/EnvironmentUpgradeView.xaml index b82be1e67..0bc763c35 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Views/EnvironmentUpgradeView.xaml +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Views/EnvironmentUpgradeView.xaml @@ -44,9 +44,11 @@ Upgrade Database Schema Upgrade Database Static Collections Upgrade Machine Studio Blob Storage - Upgrade PPC Blob Storage Upgrade Machine Studio Database Version + Upgrade PPC Blob Storage Upgrade PPC Database Version + Upgrade FSE Blob Storage + Upgrade FSE Database Version Upgrade Machine Service diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils/Database/DatabaseManager.cs b/Software/Visual_Studio/Azure/Tango.AzureUtils/Database/DatabaseManager.cs index 75a7f321b..2a94e95b0 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils/Database/DatabaseManager.cs +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils/Database/DatabaseManager.cs @@ -234,7 +234,7 @@ namespace Tango.AzureUtils.Database var targetDataSource = (await targetApp.GetMachineServiceSettingsAsync()).ToDataSource(); - OnProgress(AzureUtilsStage.Database, $"Adding machine studio database entry for version '{latestPPCVersion.Version}'..."); + OnProgress(AzureUtilsStage.Database, $"Adding PPC database entry for version '{latestPPCVersion.Version}'..."); using (var db = ObservablesContext.CreateDefault(targetDataSource)) { @@ -243,6 +243,21 @@ namespace Tango.AzureUtils.Database } } + public async Task UpgradeFSEVersion(IWebAppBase sourceApp, IWebAppBase targetApp) + { + var latestFSEVersion = await GetLatestFSEVersion(sourceApp); + + var targetDataSource = (await targetApp.GetMachineServiceSettingsAsync()).ToDataSource(); + + OnProgress(AzureUtilsStage.Database, $"Adding FSE database entry for version '{latestFSEVersion.Version}'..."); + + using (var db = ObservablesContext.CreateDefault(targetDataSource)) + { + db.FseVersions.Add(latestFSEVersion); + await db.SaveChangesAsync(); + } + } + public async Task DowngradeMachineStudioVersion(IWebAppBase app) { var latestMachineStudioVersion = await GetLatestMachineStudioVersion(app); @@ -327,8 +342,8 @@ namespace Tango.AzureUtils.Database using (var db = ObservablesContext.CreateDefault(dataSource)) { var versions = await db.TangoVersions.ToListAsync(); - var latest_machine_version = versions.OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); - return latest_machine_version; + var latest_version = versions.OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); + return latest_version; } } catch (Exception ex) @@ -337,6 +352,38 @@ namespace Tango.AzureUtils.Database } } + public async Task GetLatestFSEVersion(IWebAppBase app) + { + OnProgress(AzureUtilsStage.Database, $"Getting latest FSE version on '{app.Name}'..."); + + MachineServiceSettings settings = null; + + try + { + settings = await app.GetMachineServiceSettingsAsync(); + } + catch (Exception ex) + { + throw new ArgumentException("Could not fetch machine service settings. Please check that all settings are available.", ex); + } + + try + { + DataSource dataSource = settings.ToDataSource(); + + using (var db = ObservablesContext.CreateDefault(dataSource)) + { + var versions = await db.FseVersions.ToListAsync(); + var latest_version = versions.OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); + return latest_version; + } + } + catch (Exception ex) + { + throw new InvalidDataException($"Could not retrieve '{app.Name}' latest FSE version from database.", ex); + } + } + public async Task ValidateMachineStudioDatabaseUpgrade(IWebAppBase sourceApp, IWebAppBase targetApp) { OnProgress(AzureUtilsStage.Validating, "Validating machine studio database upgrade..."); @@ -385,6 +432,30 @@ namespace Tango.AzureUtils.Database } } + public async Task ValidateFSEDatabaseUpgrade(IWebAppBase sourceApp, IWebAppBase targetApp) + { + OnProgress(AzureUtilsStage.Validating, "Validating FSE database upgrade..."); + + var sourceSettings = await sourceApp.GetMachineServiceSettingsAsync(); + var targetSettings = await targetApp.GetMachineServiceSettingsAsync(); + + var latestSourceFSEVersion = await GetLatestFSEVersion(sourceApp); + + //Check if there is any source FSE version. + if (latestSourceFSEVersion == null) + { + throw new ValidationException("Could not locate a FSE version entry on the source database."); + } + + var latestTargetFSEVersion = await GetLatestFSEVersion(targetApp); + + //Check target latest FSE version is older if there is any. + if (latestTargetFSEVersion != null && Version.Parse(latestSourceFSEVersion.Version) <= Version.Parse(latestTargetFSEVersion.Version)) + { + throw new ValidationException($"FSE source version is '{latestSourceFSEVersion.Version}' while target version is '{latestTargetFSEVersion.Version}'."); + } + } + #endregion } } diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils/Environment/EnvironmentManager.cs b/Software/Visual_Studio/Azure/Tango.AzureUtils/Environment/EnvironmentManager.cs index 19ccb8f92..123c94f7d 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils/Environment/EnvironmentManager.cs +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils/Environment/EnvironmentManager.cs @@ -327,6 +327,20 @@ namespace Tango.AzureUtils.Environment } } + //Add FSE storage versions. + if (config.CopyFSEStorageBlobs) + { + try + { + await _storageManager.ValidateFSEStorageUpgrade(sourceApp, targetApp); + await _storageManager.UpgradeFSEStorage(sourceApp, targetApp); + } + catch (Exception ex) + { + await RequestConfirmation($"Issues encountered with upgrading FSE storage versions.\n{ex.FlattenMessage()}\nDo you wish to continue?"); + } + } + //Upgrade machine studio database version. if (config.UpgradeMachineStudioDatabaseVersion) { @@ -355,6 +369,20 @@ namespace Tango.AzureUtils.Environment } } + //Upgrade FSE database version. + if (config.UpgradeFSEDatabaseVersion) + { + try + { + await _databaseManager.ValidateFSEDatabaseUpgrade(sourceApp, targetApp); + await _databaseManager.UpgradeFSEVersion(sourceApp, targetApp); + } + catch (Exception ex) + { + await RequestConfirmation($"Issues encountered with upgrading FSE database versions.\n{ex.FlattenMessage()}\nDo you wish to continue?"); + } + } + //Copy Website files. if (config.CopyMachineServiceFiles) @@ -388,6 +416,12 @@ namespace Tango.AzureUtils.Environment await _storageManager.ValidatePPCStorageUpgrade(sourceApp, targetApp); } + //Add FSE storage versions. + if (config.CopyFSEStorageBlobs) + { + await _storageManager.ValidateFSEStorageUpgrade(sourceApp, targetApp); + } + //Upgrade machine studio database version. if (config.UpgradeMachineStudioDatabaseVersion) { @@ -399,6 +433,12 @@ namespace Tango.AzureUtils.Environment { await _databaseManager.ValidatePPCDatabaseUpgrade(sourceApp, targetApp); } + + //Upgrade FSE database version. + if (config.UpgradeFSEDatabaseVersion) + { + await _databaseManager.ValidateFSEDatabaseUpgrade(sourceApp, targetApp); + } } #endregion diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils/Environment/EnvironmentSettings.cs b/Software/Visual_Studio/Azure/Tango.AzureUtils/Environment/EnvironmentSettings.cs index 8b8e3a757..8eefc4bc5 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils/Environment/EnvironmentSettings.cs +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils/Environment/EnvironmentSettings.cs @@ -12,6 +12,7 @@ namespace Tango.AzureUtils.Environment public String DB_CATALOG { get; set; } public String MACHINE_STUDIO_VERSIONS_CONTAINER { get; set; } public String TANGO_VERSIONS_CONTAINER { get; set; } + public String FSE_VERSIONS_CONTAINER { get; set; } public String MACHINE_SERVICE_BACKUPS_CONTAINER { get; set; } public String MACHINE_SERVICE_LOGS_CONTAINER { get; set; } public String ENVIRONMENT_GROUP { get; set; } @@ -24,6 +25,7 @@ namespace Tango.AzureUtils.Environment settings.DB_CATALOG = $"Tango_{name}"; settings.MACHINE_STUDIO_VERSIONS_CONTAINER = $"machine-studio-versions-{name.ToLower()}"; settings.TANGO_VERSIONS_CONTAINER = $"tango-versions-{name.ToLower()}"; + settings.FSE_VERSIONS_CONTAINER = $"fse-versions-{name.ToLower()}"; settings.MACHINE_SERVICE_BACKUPS_CONTAINER = $"machine-service-backups-{name.ToLower()}"; settings.MACHINE_SERVICE_LOGS_CONTAINER = $"machine-service-logs-{name.ToLower()}"; settings.ENVIRONMENT_GROUP = $"Tango {name}"; diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils/Environment/UpgradeEnvironmentConfiguration.cs b/Software/Visual_Studio/Azure/Tango.AzureUtils/Environment/UpgradeEnvironmentConfiguration.cs index 537056701..1d7b9de16 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils/Environment/UpgradeEnvironmentConfiguration.cs +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils/Environment/UpgradeEnvironmentConfiguration.cs @@ -14,6 +14,8 @@ namespace Tango.AzureUtils.Environment public bool UpgradeMachineStudioDatabaseVersion { get; set; } = true; public bool CopyPPCStorageBlobs { get; set; } = true; public bool UpgradePPCDatabaseVersion { get; set; } = true; + public bool CopyFSEStorageBlobs { get; set; } = true; + public bool UpgradeFSEDatabaseVersion { get; set; } = true; public bool CopyMachineServiceFiles { get; set; } = true; } } diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils/MachineServiceSettings.cs b/Software/Visual_Studio/Azure/Tango.AzureUtils/MachineServiceSettings.cs index 93065c50d..4f8742083 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils/MachineServiceSettings.cs +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils/MachineServiceSettings.cs @@ -18,5 +18,6 @@ namespace Tango.AzureUtils public String MACHINE_STUDIO_VERSIONS_CONTAINER { get; set; } public String STORAGE_ACCOUNT { get; set; } public String TANGO_VERSIONS_CONTAINER { get; set; } + public String FSE_VERSIONS_CONTAINER { get; set; } } } diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils/Storage/StorageManager.cs b/Software/Visual_Studio/Azure/Tango.AzureUtils/Storage/StorageManager.cs index 77a0aaf6d..db4403cc9 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils/Storage/StorageManager.cs +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils/Storage/StorageManager.cs @@ -109,6 +109,39 @@ namespace Tango.AzureUtils.Storage }); } + public async Task UpgradeFSEStorage(IWebAppBase sourceApp, IWebAppBase targetApp) + { + OnProgress(AzureUtilsStage.Storage, $"Retrieving source and target settings..."); + + var sourceSettings = await sourceApp.GetMachineServiceSettingsAsync(); + var targetSettings = await targetApp.GetMachineServiceSettingsAsync(); + + var latestFSEVersion = await _databaseManager.GetLatestFSEVersion(sourceApp); + + OnProgress(AzureUtilsStage.Storage, $"Upgrading FSE version storage..."); + + var sourceAccount = CloudStorageAccount.Parse(sourceSettings.STORAGE_ACCOUNT); + var sourceClient = sourceAccount.CreateCloudBlobClient(); + + var targetAccount = CloudStorageAccount.Parse(targetSettings.STORAGE_ACCOUNT); + var targetClient = targetAccount.CreateCloudBlobClient(); + + var sourceFSEContainer = sourceClient.GetContainerReference(sourceSettings.FSE_VERSIONS_CONTAINER); + var targetFSEContainer = targetClient.GetContainerReference(targetSettings.FSE_VERSIONS_CONTAINER); + + //var sourceFSEBlob = sourceFSEContainer.GetBlockBlobReference(latestPPCVersion.BlobName); + var sourceFSEInstallerBlob = sourceFSEContainer.GetBlockBlobReference(latestFSEVersion.InstallerBlobName); + + //var targetFSEBlob = await CreateEmptyBlob(targetFSEContainer, sourceFSEBlob.Name); + var targetFSEInstallerBlob = await CreateEmptyBlob(targetFSEContainer, sourceFSEInstallerBlob.Name); + + await Task.Factory.StartNew(() => + { + //targetFSEBlob.StartCopy(sourceFSEBlob); + targetFSEInstallerBlob.StartCopy(sourceFSEInstallerBlob); + }); + } + public async Task UpgradeMachineStudioStorage(IWebAppBase sourceApp, IWebAppBase targetApp) { OnProgress(AzureUtilsStage.Storage, $"Retrieving source and target settings..."); @@ -170,7 +203,7 @@ namespace Tango.AzureUtils.Storage public async Task ValidatePPCStorageUpgrade(IWebAppBase sourceApp, IWebAppBase targetApp) { - OnProgress(AzureUtilsStage.Validating, "Validating PPC database upgrade..."); + OnProgress(AzureUtilsStage.Validating, "Validating PPC storage upgrade..."); var sourceSettings = await sourceApp.GetMachineServiceSettingsAsync(); var targetSettings = await targetApp.GetMachineServiceSettingsAsync(); @@ -198,6 +231,36 @@ namespace Tango.AzureUtils.Storage } } + public async Task ValidateFSEStorageUpgrade(IWebAppBase sourceApp, IWebAppBase targetApp) + { + OnProgress(AzureUtilsStage.Validating, "Validating FSE storage upgrade..."); + + var sourceSettings = await sourceApp.GetMachineServiceSettingsAsync(); + var targetSettings = await targetApp.GetMachineServiceSettingsAsync(); + + var latestSourceFSEVersion = await _databaseManager.GetLatestFSEVersion(sourceApp); + var latestTargetFSEVersion = await _databaseManager.GetLatestFSEVersion(targetApp); + + var targetAccount = CloudStorageAccount.Parse(targetSettings.STORAGE_ACCOUNT); + var targetClient = targetAccount.CreateCloudBlobClient(); + + var targetFSEContainer = targetClient.GetContainerReference(targetSettings.FSE_VERSIONS_CONTAINER); + + //Check FSE binaries blob not exists on the target. + var targetFSEBlob = targetFSEContainer.GetBlockBlobReference(latestSourceFSEVersion.BlobName); + if (await targetFSEBlob.ExistsAsync()) + { + throw new ValidationException($"FSE Block blob '{latestSourceFSEVersion.BlobName}' already exists on the target storage."); + } + + //Check FSE installer blob not exists on the target. + var targetFSEInstallerBlob = targetFSEContainer.GetBlockBlobReference(latestSourceFSEVersion.InstallerBlobName); + if (await targetFSEInstallerBlob.ExistsAsync()) + { + throw new ValidationException($"FSE Block blob '{latestSourceFSEVersion.InstallerBlobName}' already exists on the target storage."); + } + } + public async Task ValidateMachineStudioStorageUpgrade(IWebAppBase sourceApp, IWebAppBase targetApp) { OnProgress(AzureUtilsStage.Validating, "Validating machine studio storage upgrade..."); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs index 68420ea67..2151f03d1 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs @@ -93,5 +93,32 @@ namespace Tango.FSE.BL.Web return Post("SendForgotPasswordEmail", request); } + /// + /// Executes the GetLatestVersion action and returns Tango.FSE.Web.Messages.LatestVersionResponse. + /// + /// + public Task GetLatestVersion(Tango.FSE.Web.Messages.LatestVersionRequest request) + { + return Post("GetLatestVersion", request); + } + + /// + /// Executes the UploadVersion action and returns Tango.FSE.Web.Messages.UploadVersionResponse. + /// + /// + public Task UploadVersion(Tango.FSE.Web.Messages.UploadVersionRequest request) + { + return Post("UploadVersion", request); + } + + /// + /// Executes the NotifyVersionUploadCompleted action and returns Tango.FSE.Web.Messages.UploadCompletedResponse. + /// + /// + public Task NotifyVersionUploadCompleted(Tango.FSE.Web.Messages.UploadCompletedRequest request) + { + return Post("NotifyVersionUploadCompleted", request); + } + } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/App.config b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/App.config new file mode 100644 index 000000000..3c53533de --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/App.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/App.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/App.xaml new file mode 100644 index 000000000..ccf0edb6b --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/App.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/App.xaml.cs new file mode 100644 index 000000000..3a9bfe8d8 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/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.FSE.Publisher.UI +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/MainWindow.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/MainWindow.xaml new file mode 100644 index 000000000..143113bf1 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/MainWindow.xaml @@ -0,0 +1,66 @@ + + + + + + + + Tango FSE Publish Utility + + + + + + + + + Environment: + + + + + Build Configuration: + + Release + Debug + + + + + Remote Version: + + + + + Local Version: + + + + Comments + + + Email + + + Password + + + + + + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/MainWindow.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/MainWindow.xaml.cs new file mode 100644 index 000000000..7a4ddc19f --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/MainWindow.xaml.cs @@ -0,0 +1,34 @@ +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.FSE.Publisher.UI +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + var vm = new MainWindowVM(); + DataContext = vm; + ContentRendered += (_, __) => + { + vm.Init(); + }; + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/MainWindowVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/MainWindowVM.cs new file mode 100644 index 000000000..148ee37f6 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/MainWindowVM.cs @@ -0,0 +1,316 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using Tango.AdvancedInstaller; +using Tango.Core; +using Tango.Core.Commands; +using Tango.FSE.BL.Web; +using Tango.FSE.Web.Messages; +using Tango.MachineService.Gateway; +using Tango.Settings; +using Tango.SharedUI; +using Tango.Transport.Web; + +namespace Tango.FSE.Publisher.UI +{ + public class MainWindowVM : ViewModel + { + private FSEWebClient _client; + private String _buildFolder; + private const String APP_EXE_NAME = "Tango.FSE.UI.exe"; + + private List _environments; + public List Environments + { + get { return _environments; } + set { _environments = value; RaisePropertyChangedAuto(); } + } + + private EnvironmentConfiguration _selectedEnvironment; + public EnvironmentConfiguration SelectedEnvironment + { + get { return _selectedEnvironment; } + set { _selectedEnvironment = value; RaisePropertyChangedAuto(); OnSelectedEnvironmentChanged(); InvalidateRelayCommands(); } + } + + private String _localVersion; + public String LocalVersion + { + get { return _localVersion; } + set { _localVersion = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + private String _remoteVersion; + public String RemoteVersion + { + get { return _remoteVersion; } + set { _remoteVersion = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + private String _buidConfig; + public String BuildConfig + { + get { return _buidConfig; } + set { _buidConfig = value; RaisePropertyChangedAuto(); OnBuildConfigChanged(); InvalidateRelayCommands(); } + } + + private String _email; + public String Email + { + get { return _email; } + set { _email = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + private String _password; + public String Password + { + get { return _password; } + set { _password = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + private String _comments; + public String Comments + { + get { return _comments; } + set { _comments = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + private TangoProgress _progress; + public TangoProgress Progress + { + get { return _progress; } + set { _progress = value; RaisePropertyChangedAuto(); } + } + + + public RelayCommand PublishCommand { get; set; } + + public MainWindowVM() + { + PublishCommand = new RelayCommand(Publish, CanPublish); + + var settings = SettingsManager.Default.GetOrCreate(); + Email = settings.Email; + Password = settings.Password; + } + + private bool CanPublish() + { + try + { + return + SelectedEnvironment != null && + Email.IsNotNullOrEmpty() && + Password.IsNotNullOrEmpty() && + Comments.IsNotNullOrEmpty() && + System.Version.Parse(LocalVersion) > System.Version.Parse(RemoteVersion) && + IsFree; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return false; + } + } + + public async void Init() + { + try + { + IsFree = false; + UpdateProgress("Retrieving environments..."); + using (HttpClient http = new HttpClient()) + { + GatewayClient client = new GatewayClient(ConfigurationManager.AppSettings.Get("GatewayUrl"), http); + Environments = (await client.GetEnvironmentsAsync(new EnvironmentsRequest())).Environments.OrderBy(x => x.DisplayIndex).ToList(); + } + + SelectedEnvironment = Environments.SingleOrDefault(x => x.Name == "TEST"); + + BuildConfig = "Release"; + + ProgressReady(); + } + catch (Exception ex) + { + ShowError($"Error retrieving environments from gateway service.\n{ex.FlattenMessage()}"); + } + finally + { + IsFree = true; + } + } + + private void OnBuildConfigChanged() + { + UpdateProgress("Searching build path..."); + + String path = Path.GetFullPath($@"../../../../Build\FSE\{BuildConfig}"); + if (!Directory.Exists(path)) + { + ShowError($"Could not locate FSE build folder at '{path}'."); + } + + _buildFolder = path; + + try + { + String appExe = Path.Combine(path, APP_EXE_NAME); + LocalVersion = FileVersionInfo.GetVersionInfo(appExe).ProductVersion; + ProgressReady(); + } + catch (Exception ex) + { + ShowError($"Could not determine the local application version.\n{ex.FlattenMessage()}"); + } + } + + private async Task OnSelectedEnvironmentChanged() + { + if (SelectedEnvironment != null) + { + try + { + IsFree = false; + UpdateProgress("Getting remote version..."); + _client = new FSEWebClient(SelectedEnvironment.MachineServiceAddress); + RemoteVersion = (await _client.GetLatestVersion(new Web.Messages.LatestVersionRequest())).Version; + ProgressReady(); + } + catch (Exception ex) + { + ShowError($"Error retrieving the remote version.\n{ex.FlattenMessage()}"); + } + finally + { + IsFree = true; + } + } + } + + private async void Publish() + { + try + { + IsFree = false; + UpdateProgress("Publishing Tango FSE..."); + + var settings = SettingsManager.Default.GetOrCreate(); + settings.Email = Email; + settings.Password = Password; + settings.Save(); + + UpdateProgress("Validating Tango FSE installer...."); + + String projectPath = Path.GetFullPath(@"../../../../Advanced Installer Projects\FSE Installer.aip"); + + if (!File.Exists(projectPath)) + { + throw new FileNotFoundException($"Could not locate advanced installer project at '{projectPath}'."); + } + + String installerName = $"Tango FSE v{System.Version.Parse(LocalVersion).ToString(3)}.exe"; + String installerPath = Path.GetFullPath($@"../../../../Build\Installers\FSE\Release\{installerName}"); + + if (!Directory.Exists(Path.GetDirectoryName(installerPath))) + { + throw new DirectoryNotFoundException($"Could not locate installer output directory '{Path.GetDirectoryName(installerPath)}'."); + } + + UpdateProgress("Authenticating with machine service..."); + await _client.Login(new LoginRequest() + { + Email = Email, + Password = Password, + Version = LocalVersion + }); + + UpdateProgress("Requesting version upload..."); + var uploadResponse = await _client.UploadVersion(new UploadVersionRequest() + { + Comments = Comments, + InstallerBlobName = installerName, + Version = LocalVersion + }); + + UpdateProgress("Building Tango FSE installer..."); + + InstallerBuilder builder = new InstallerBuilder(projectPath); + await builder.Build(LocalVersion, installerPath); + + if (!File.Exists(installerPath)) + { + throw new FileNotFoundException($"Installer build was successful but the output installer could not be located at the specified path '{installerPath}'."); + } + + UpdateProgress("Uploading Tango FSE installer..."); + + using (StorageBlobUploader uploader = new StorageBlobUploader(uploadResponse.InstallerBlobAddress, installerPath)) + { + uploader.Progress += (x, e) => + { + UpdateProgress("Uploading Tango FSE installer...", false, e.Current, e.Total); + }; + + await uploader.Upload(); + } + + UpdateProgress("Finalizing version publishing..."); + + await _client.NotifyVersionUploadCompleted(new UploadCompletedRequest() + { + Token = uploadResponse.Token + }); + + UpdateProgress("Validating..."); + await OnSelectedEnvironmentChanged(); + + if (LocalVersion != RemoteVersion) + { + throw new InvalidDataException("Publishing completed but the local and remote versions are different?!"); + } + + Process.Start(SelectedEnvironment.MachineServiceAddress + "/fse"); + + UpdateProgress("Version published successfully!", false, 100, 100); + ShowInfo("Tango FSE published successfully!"); + } + catch (Exception ex) + { + ShowError($"Error while trying to publish Tango FSE\n{ex.FlattenMessage()}"); + } + finally + { + IsFree = true; + } + } + + private void ShowError(String error) + { + UpdateProgress("Error!", false, 0, 100); + MessageBox.Show(error, "FSE Publisher", MessageBoxButton.OK, MessageBoxImage.Error); + } + + private void ShowInfo(String message) + { + MessageBox.Show(message, "FSE Publisher", MessageBoxButton.OK, MessageBoxImage.Information); + } + + private void UpdateProgress(String message, bool isIndeterminate = true, double value = 0, double max = 100) + { + Progress = new TangoProgress(message, isIndeterminate, value, max); + } + + private void ProgressReady() + { + UpdateProgress("Ready", false, 0, 100); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/AssemblyInfo.cs b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..970139e8e --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Tango.FSE.Publisher.UI")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Tango.FSE.Publisher.UI")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/Resources.Designer.cs b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/Resources.Designer.cs new file mode 100644 index 000000000..48dfa2514 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/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.FSE.Publisher.UI.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.FSE.Publisher.UI.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/FSE/Tango.FSE.Publisher.UI/Properties/Resources.resx b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/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/FSE/Tango.FSE.Publisher.UI/Properties/Settings.Designer.cs b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/Settings.Designer.cs new file mode 100644 index 000000000..05f0c70e0 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/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.FSE.Publisher.UI.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/FSE/Tango.FSE.Publisher.UI/Properties/Settings.settings b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/Settings.settings new file mode 100644 index 000000000..033d7a5e9 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/PublisherSettings.cs b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/PublisherSettings.cs new file mode 100644 index 000000000..f2fd98b9c --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/PublisherSettings.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Settings; + +namespace Tango.FSE.Publisher.UI +{ + public class PublisherSettings : SettingsBase + { + public String Email { get; set; } + public String Password { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Tango.FSE.Publisher.UI.csproj b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Tango.FSE.Publisher.UI.csproj new file mode 100644 index 000000000..26a0ee007 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Publisher.UI/Tango.FSE.Publisher.UI.csproj @@ -0,0 +1,141 @@ + + + + + Debug + AnyCPU + {4C045668-9E5A-447A-A3B8-106C872C1039} + WinExe + Tango.FSE.Publisher.UI + Tango.FSE.Publisher.UI + v4.6.1 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + MainWindow.xaml + Code + + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + {c5df1816-34e5-4700-824c-29623a1baa22} + Tango.AdvancedInstaller + + + {a34ee0f0-649d-41c8-8489-b6f1cc6924ee} + Tango.Core + + + {d8f1ad85-526a-4f50-b6dc-d437af63d8d8} + Tango.Settings + + + {8491d07b-c1f6-4b62-a412-41b9fd2d6538} + Tango.SharedUI + + + {74e700b0-1156-4126-be40-ee450d3c3026} + Tango.Transport + + + {5001990f-977b-48ff-b217-0236a5022ad8} + Tango.Web + + + {834c81c3-09b5-45d7-be12-e7d1e6655a7c} + Tango.FSE.BL + + + {bc37cccb-7392-4f78-8d1c-e9629e6e046e} + Tango.FSE.Common + + + {d6f7d31d-7f8c-45e2-ae0a-fbbd1f5f9d5f} + Tango.FSE.Web + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs index 9121fb2f1..4a0bc1496 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs @@ -8,5 +8,5 @@ using System.Windows; // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Tango FSE")] -[assembly: AssemblyVersion("1.0.2.0")] +[assembly: AssemblyVersion("1.0.3.0")] diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/LatestVersionRequest.cs b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/LatestVersionRequest.cs new file mode 100644 index 000000000..8f6117241 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/LatestVersionRequest.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Tango.Transport.Web; + +namespace Tango.FSE.Web.Messages +{ + public class LatestVersionRequest : WebRequestMessage + { + + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/LatestVersionResponse.cs b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/LatestVersionResponse.cs new file mode 100644 index 000000000..3b239567c --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/LatestVersionResponse.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Tango.Transport.Web; + +namespace Tango.FSE.Web.Messages +{ + public class LatestVersionResponse : WebResponseMessage + { + public String Version { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadCompletedRequest.cs b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadCompletedRequest.cs new file mode 100644 index 000000000..a82ac0083 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadCompletedRequest.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Tango.Transport.Web; + +namespace Tango.FSE.Web.Messages +{ + public class UploadCompletedRequest : WebRequestMessage + { + public String Token { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadCompletedResponse.cs b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadCompletedResponse.cs new file mode 100644 index 000000000..065ccc3ce --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadCompletedResponse.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Transport.Web; + +namespace Tango.FSE.Web.Messages +{ + public class UploadCompletedResponse : WebResponseMessage + { + + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadVersionRequest.cs b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadVersionRequest.cs new file mode 100644 index 000000000..01968d249 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadVersionRequest.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Tango.Transport.Web; + +namespace Tango.FSE.Web.Messages +{ + public class UploadVersionRequest : WebRequestMessage + { + public String Version { get; set; } + + public String Comments { get; set; } + + public String InstallerBlobName { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadVersionResponse.cs b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadVersionResponse.cs new file mode 100644 index 000000000..1ea801b63 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UploadVersionResponse.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Tango.Transport.Web; + +namespace Tango.FSE.Web.Messages +{ + public class UploadVersionResponse : WebResponseMessage + { + public String Token { get; set; } + + public String BlobAddress { get; set; } + + public String InstallerBlobAddress { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj b/Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj index 4c9f769c4..7c6e70919 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj @@ -49,10 +49,16 @@ + + + + + + diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln index 51788b0d2..c28ad8850 100644 --- a/Software/Visual_Studio/Tango.sln +++ b/Software/Visual_Studio/Tango.sln @@ -401,6 +401,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.ColorLib.GradientTest EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.FSE.Procedures", "FSE\Modules\Tango.FSE.Procedures\Tango.FSE.Procedures.csproj", "{1754F846-4763-4000-807F-C7BFAA145DB2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.FSE.Publisher.UI", "FSE\Tango.FSE.Publisher.UI\Tango.FSE.Publisher.UI.csproj", "{4C045668-9E5A-447A-A3B8-106C872C1039}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -3748,6 +3750,26 @@ Global {1754F846-4763-4000-807F-C7BFAA145DB2}.Release|x64.Build.0 = Release|Any CPU {1754F846-4763-4000-807F-C7BFAA145DB2}.Release|x86.ActiveCfg = Release|Any CPU {1754F846-4763-4000-807F-C7BFAA145DB2}.Release|x86.Build.0 = Release|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Debug|ARM.ActiveCfg = Debug|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Debug|ARM.Build.0 = Debug|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Debug|ARM64.Build.0 = Debug|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Debug|x64.ActiveCfg = Debug|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Debug|x64.Build.0 = Debug|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Debug|x86.ActiveCfg = Debug|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Debug|x86.Build.0 = Debug|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Release|Any CPU.Build.0 = Release|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Release|ARM.ActiveCfg = Release|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Release|ARM.Build.0 = Release|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Release|ARM64.ActiveCfg = Release|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Release|ARM64.Build.0 = Release|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Release|x64.ActiveCfg = Release|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Release|x64.Build.0 = Release|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Release|x86.ActiveCfg = Release|Any CPU + {4C045668-9E5A-447A-A3B8-106C872C1039}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3884,6 +3906,7 @@ Global {8336A702-9C49-4C9E-ADCC-1886A666D3BD} = {7181F9DE-0760-46B7-AD8F-BDBCAEDEF1B7} {982C6FAC-2864-484E-82AE-5A36658C4DB1} = {8336A702-9C49-4C9E-ADCC-1886A666D3BD} {1754F846-4763-4000-807F-C7BFAA145DB2} = {4EE6DBA1-71BC-49E2-8DC7-266487E61050} + {4C045668-9E5A-447A-A3B8-106C872C1039} = {004337EB-0761-4D30-B9F5-AE6E1CFC6013} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution BuildVersion_UseGlobalSettings = False diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs index e471ed20c..387430f89 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs @@ -25,11 +25,15 @@ using Tango.Web.SQLServer; using Tango.Web.Storage; using System.Data.Entity; using static Tango.MachineService.Controllers.FSEController; +using Tango.MachineService.Models; +using Tango.BL.Enumerations; namespace Tango.MachineService.Controllers { public class FSEController : TangoController { + private static List _pendingUploads; + public class TokenObject { public String UserGuid { get; set; } @@ -46,6 +50,7 @@ namespace Tango.MachineService.Controllers static FSEController() { + _pendingUploads = new List(); PendingPasswordResets = new List(); } @@ -323,5 +328,104 @@ namespace Tango.MachineService.Controllers return new ForgotPasswordResponse(); } + + #region Version Upload + + [HttpPost] + public LatestVersionResponse GetLatestVersion(LatestVersionRequest request) + { + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + var version = db.FseVersions.ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); + return new LatestVersionResponse() { Version = version != null ? version.Version : "0.0.0.0" }; + } + } + + [HttpPost] + [JwtTokenFilter] + public UploadVersionResponse UploadVersion(UploadVersionRequest request) + { + UploadVersionResponse response = new UploadVersionResponse(); + + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + String userID = RequestToken.Object.UserGuid; + + var user = new UserBuilder(db).Set(userID).WithRolesAndPermissions().Build(); + + if (user != null && user.HasPermission(Permissions.PublishMachineStudioVersions)) + +{ + var latestVersion = db.FseVersions.ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); + Version local_version = Version.Parse(request.Version); + + if (latestVersion == null || local_version > Version.Parse(latestVersion.Version)) + { + var manager = new BlobStorageManager(); + var container = manager.GetContainer(MachineServiceConfig.FSE_VERSIONS_CONTAINER); + var installerBlob = container.CreateEmptyBlob(request.InstallerBlobName); + + response.Token = Guid.NewGuid().ToString(); + response.InstallerBlobAddress = installerBlob.GenerateWriteSignature(TimeSpan.FromMinutes(30)); + + FSEPendingUpload pending_upload = new FSEPendingUpload() + { + UserGuid = user.Guid, + Comments = request.Comments, + Token = response.Token, + Version = request.Version, + BlobName = "BLOB", + InstallerBlobName = installerBlob.Name + }; + + _pendingUploads.Add(pending_upload); + } + else + { + throw new ArgumentException("New version must be greater than latest version."); + } + } + else + { + throw new AuthenticationException("Invalid user credentials."); + } + } + + return response; + } + + [HttpPost] + [JwtTokenFilter] + public UploadCompletedResponse NotifyVersionUploadCompleted(UploadCompletedRequest request) + { + FSEPendingUpload upload = _pendingUploads.FirstOrDefault(x => x.Token == request.Token); + + if (upload != null) + { + _pendingUploads.RemoveAll(x => x.Token == upload.Token); + + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + db.FseVersions.Add(new FseVersion() + { + Comments = upload.Comments, + BlobName = upload.BlobName, + InstallerBlobName = upload.InstallerBlobName, + UserGuid = upload.UserGuid, + Version = upload.Version, + }); + + db.SaveChanges(); + } + + return new UploadCompletedResponse(); + } + else + { + throw new ArgumentException("Invalid Token."); + } + } + + #endregion } } diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Models/FSEPendingUpload.cs b/Software/Visual_Studio/Web/Tango.MachineService/Models/FSEPendingUpload.cs new file mode 100644 index 000000000..7bb74d045 --- /dev/null +++ b/Software/Visual_Studio/Web/Tango.MachineService/Models/FSEPendingUpload.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace Tango.MachineService.Models +{ + public class FSEPendingUpload + { + public String Token { get; set; } + + public String Version { get; set; } + + public String UserGuid { get; set; } + + public String Comments { get; set; } + + public String BlobName { get; set; } + + public String InstallerBlobName { get; set; } + } +} \ No newline at end of file diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj b/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj index 9b25a25a8..c662b1e87 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj +++ b/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj @@ -327,6 +327,7 @@ + @@ -489,7 +490,7 @@ False - + -- cgit v1.3.1 From 0281068b4adb3f94af50f2c758d3e0fa0fe5f191 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Tue, 28 Jul 2020 15:50:27 +0300 Subject: Added machine service version display to AzureUtils. --- .../Controls/WebAppPropertiesControl.xaml | 3 +++ .../Controls/WebAppPropertiesControl.xaml.cs | 14 ++++++++++++++ .../Azure/Tango.AzureUtils.UI/MainWindow.xaml | 2 +- .../Azure/Tango.AzureUtils/FTP/FtpManager.cs | 17 +++++++++++++++++ .../Web/Tango.MachineService/Properties/AssemblyInfo.cs | 2 +- 5 files changed, 36 insertions(+), 2 deletions(-) (limited to 'Software/Visual_Studio/Web/Tango.MachineService') diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml index aadfb7918..6eb78c808 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml @@ -64,6 +64,9 @@ Tango FSE Version: + + Machine Service Version: + diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml.cs b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml.cs index 8888dfc02..129550d14 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml.cs +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml.cs @@ -14,6 +14,7 @@ using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using Tango.AzureUtils.Database; +using Tango.AzureUtils.FTP; using Tango.BL.Entities; namespace Tango.AzureUtils.UI.Controls @@ -63,6 +64,16 @@ namespace Tango.AzureUtils.UI.Controls public static readonly DependencyProperty MachineStudioVersionProperty = DependencyProperty.Register("MachineStudioVersion", typeof(MachineStudioVersion), typeof(WebAppPropertiesControl), new PropertyMetadata(null)); + public String MachineServiceVersion + { + get { return (String)GetValue(MachineServiceVersionProperty); } + set { SetValue(MachineServiceVersionProperty, value); } + } + public static readonly DependencyProperty MachineServiceVersionProperty = + DependencyProperty.Register("MachineServiceVersion", typeof(String), typeof(WebAppPropertiesControl), new PropertyMetadata(null)); + + + public bool IsBusy { get { return (bool)GetValue(IsBusyProperty); } @@ -97,6 +108,9 @@ namespace Tango.AzureUtils.UI.Controls TangoVersion = await databaseManager.GetLatestPPCVersion(app); MachineStudioVersion = await databaseManager.GetLatestMachineStudioVersion(app); FseVersion = await databaseManager.GetLatestFSEVersion(app); + + FtpManager ftpManager = new FtpManager(azure); + MachineServiceVersion = await ftpManager.GetMachineServiceVersion(app); } catch { } finally diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/MainWindow.xaml b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/MainWindow.xaml index 6eaedea2a..d23fd41d8 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/MainWindow.xaml +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/MainWindow.xaml @@ -6,7 +6,7 @@ xmlns:views="clr-namespace:Tango.AzureUtils.UI.Views" xmlns:local="clr-namespace:Tango.AzureUtils.UI" mc:Ignorable="d" - Title="Azure Utils" Height="920" Width="1280"> + Title="Azure Utils" Height="950" Width="1280" WindowStartupLocation="CenterScreen"> diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils/FTP/FtpManager.cs b/Software/Visual_Studio/Azure/Tango.AzureUtils/FTP/FtpManager.cs index 5a174dcb2..021426d12 100644 --- a/Software/Visual_Studio/Azure/Tango.AzureUtils/FTP/FtpManager.cs +++ b/Software/Visual_Studio/Azure/Tango.AzureUtils/FTP/FtpManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Security.Authentication; using System.Text; @@ -115,5 +116,21 @@ namespace Tango.AzureUtils.FTP var downloadResults = await DownloadWebAppFiles(sourceApp, webAppFilesTempFolder); var uploadResults = await UploadWebAppFiles(targetApp, webAppFilesTempFolder); } + + public async Task GetMachineServiceVersion(IWebAppBase app) + { + var exeTempFile = TemporaryManager.CreateImaginaryFile(".dll"); + + var profile = await app.GetPublishingProfileAsync(); + + using (var ftp = CreateFtpClient(profile.FtpUrl, profile.FtpUsername, profile.FtpPassword)) + { + await ftp.ConnectAsync(); + await ftp.DownloadFileAsync(exeTempFile, "/site/wwwroot/bin/Tango.MachineService.dll"); + String version = FileVersionInfo.GetVersionInfo(exeTempFile).ProductVersion; + await exeTempFile.DeleteAsync(); + return version; + } + } } } diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs index 142676f82..386a7c4b8 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs @@ -24,4 +24,4 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("2.0.*")] +[assembly: AssemblyVersion("3.0.0.0")] -- cgit v1.3.1 From 03bc9bd370929884f98ee9488146646d44911efd Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Wed, 5 Aug 2020 22:18:14 +0300 Subject: Improved PPC Publisher for Firmware version display and validation. --- .../PPC/Tango.PPC.Common/Publish/PPCPublisher.cs | 32 ++++++++++++++++------ .../PPC/Tango.PPC.Common/Publish/PublishOptions.cs | 3 +- .../Tango.PPC.Common/Web/LatestVersionResponse.cs | 1 + .../PPC/Tango.PPC.Publisher.UI/MainWindow.xaml | 10 ++++--- .../PPC/Tango.PPC.Publisher.UI/MainWindowVM.cs | 26 +++++++++++++++++- .../Controllers/PPCController.cs | 5 +++- .../Properties/AssemblyInfo.cs | 2 +- 7 files changed, 63 insertions(+), 16 deletions(-) (limited to 'Software/Visual_Studio/Web/Tango.MachineService') diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PPCPublisher.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PPCPublisher.cs index 2fc2ca507..a28cc747a 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PPCPublisher.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PPCPublisher.cs @@ -59,14 +59,11 @@ namespace Tango.PPC.Common.Publish /// Gets the latest version. /// /// - public async Task GetRemoteVersion(String machineVersionGuid) + public async Task GetRemoteVersion(String machineVersionGuid) { _client.Environment = Options.Environment; - var response = await _client.GetLatestVersion(new LatestVersionRequest() - { - MachineVersionGuid = machineVersionGuid, - }); - return response.Version; + var response = await _client.GetLatestVersion(new LatestVersionRequest() { MachineVersionGuid = machineVersionGuid } ); + return response; } /// @@ -163,8 +160,12 @@ namespace Tango.PPC.Common.Publish OnPublishProgress(0, 100, $"Fetching remote version from {Options.Environment.ToAddress()}..."); - String remote_version = GetRemoteVersion(Options.MachineVersionGuid).Result; + var r = GetRemoteVersion(Options.MachineVersionGuid).Result; + String remote_version = r.Version; + String remote_firmware_version = r.FirmwareVersion; + String local_version = GetLocalVersion(); + String local_firmware_version = GetLocalFirmwareVersion(Options.TfpPath); OnPublishProgress(0, 100, $"Remote version: {remote_version}"); OnPublishProgress(0, 100, $"Local version: {local_version}"); @@ -174,6 +175,11 @@ namespace Tango.PPC.Common.Publish throw new InvalidOperationException($"The local version '{local_version}' is not greater than the remote version '{remote_version}'."); } + if (Version.Parse(local_firmware_version) <= Version.Parse(remote_firmware_version)) + { + throw new InvalidOperationException($"The local firmware version '{local_firmware_version}' is not greater than the remote version '{remote_firmware_version}'."); + } + OnPublishProgress(0, 100, $"Requesting version upload..."); var response = _client.UploadVersion(new UploadVersionRequest() @@ -233,7 +239,7 @@ namespace Tango.PPC.Common.Publish Token = response.Token, }).Wait(); - remote_version = GetRemoteVersion(Options.MachineVersionGuid).Result; + remote_version = GetRemoteVersion(Options.MachineVersionGuid).Result.Version; local_version = GetLocalVersion(); OnPublishProgress(0, 0, $"Remote version: {remote_version}"); @@ -412,6 +418,16 @@ namespace Tango.PPC.Common.Publish } } + /// + /// Gets the MCU version from the specified TFP file. + /// + /// The TFP file. + /// + public String GetLocalFirmwareVersion(String tfpFile) + { + return GetVersionInfoFromTFP(tfpFile).GetMcuVersion().ToString(); + } + /// /// Raises the publish progress event. /// diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishOptions.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishOptions.cs index 4c40acb44..9b8613cfb 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishOptions.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishOptions.cs @@ -17,6 +17,7 @@ namespace Tango.PPC.Common.Publish public event EventHandler BuidConfigChanged; public event EventHandler BasicInfoChanged; public event EventHandler MachineVersionGuidChanged; + public event EventHandler TfpPathChanged; private String basePath; [Option("path", HelpText = "Specifies the application base path.", Required = false)] @@ -79,7 +80,7 @@ namespace Tango.PPC.Common.Publish public String TfpPath { get { return _tfpPath; } - set { _tfpPath = value; RaisePropertyChangedAuto(); } + set { _tfpPath = value; RaisePropertyChangedAuto(); TfpPathChanged?.Invoke(this, new EventArgs()); } } private String _installerProject; diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/LatestVersionResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/LatestVersionResponse.cs index d2ed08f7d..eb5ef7f5a 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/LatestVersionResponse.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/LatestVersionResponse.cs @@ -11,5 +11,6 @@ namespace Tango.PPC.Common.Web public class LatestVersionResponse : WebResponseMessage { public String Version { get; set; } + public String FirmwareVersion { get; set; } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindow.xaml b/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindow.xaml index f74194222..1d60a70be 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindow.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindow.xaml @@ -67,15 +67,17 @@ - Remote Version: - + Remote Versions: + , + - Local Version: - + Local Versions: + , + diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindowVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindowVM.cs index 98b35ed3f..d935c44d2 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindowVM.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindowVM.cs @@ -67,6 +67,13 @@ namespace Tango.PPC.Publisher.UI set { _localVersion = value; RaisePropertyChangedAuto(); } } + private String _localFirmwareVersion; + public String LocalFirmwareVersion + { + get { return _localFirmwareVersion; } + set { _localFirmwareVersion = value; RaisePropertyChangedAuto(); } + } + private String _remoteVersion; public String RemoteVersion { @@ -74,6 +81,13 @@ namespace Tango.PPC.Publisher.UI set { _remoteVersion = value; RaisePropertyChangedAuto(); } } + private String _remoteFirmwareVersion; + public String RemoteFirmwareVersion + { + get { return _remoteFirmwareVersion; } + set { _remoteFirmwareVersion = value; RaisePropertyChangedAuto(); } + } + private ICollectionView _provisionSequenceItemsView; public ICollectionView ProvisionSequenceItemsView { @@ -127,6 +141,7 @@ namespace Tango.PPC.Publisher.UI Options.BasicInfoChanged += (_, __) => InvalidateRelayCommands(); Options.EnvironmentChanged += async (_, __) => await OnEnvironmentChanged(); Options.BuidConfigChanged += async (_, __) => await UpdateVersions(); + Options.TfpPathChanged += async (_, __) => await UpdateVersions(); Init(); } @@ -165,9 +180,18 @@ namespace Tango.PPC.Publisher.UI { IsFree = false; LocalVersion = _publisher.GetLocalVersion(); + + try + { + LocalFirmwareVersion = _publisher.GetLocalFirmwareVersion(Options.TfpPath); + } + catch {} + if (SelectedMachineVersion != null) { - RemoteVersion = await _publisher.GetRemoteVersion(SelectedMachineVersion.Guid); + var latestVersion = await _publisher.GetRemoteVersion(SelectedMachineVersion.Guid); + RemoteVersion = latestVersion.Version; + RemoteFirmwareVersion = latestVersion.FirmwareVersion; } InvalidateRelayCommands(); IsFree = true; diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs index 10af2f725..22feb29c1 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs @@ -788,10 +788,13 @@ namespace Tango.MachineService.Controllers return new LatestVersionResponse() { Version = "0.0.0.0", + FirmwareVersion = "0.0.0.0" }; } - response.Version = versions.OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault().Version; + var latestTangoVersion = versions.OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); + response.Version = latestTangoVersion.Version; + response.FirmwareVersion = latestTangoVersion.FirmwareVersion; } return response; diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs index 386a7c4b8..a6aa93dee 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs @@ -24,4 +24,4 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("3.0.0.0")] +[assembly: AssemblyVersion("3.0.1.0")] -- cgit v1.3.1 From f809df07060dc3a27167f68027eb03bdbc89221a Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Sat, 15 Aug 2020 19:13:10 +0300 Subject: File Associations DDE!! --- .../FSE/File Associations/procedure_dde.ico | Bin 0 -> 107997 bytes .../FSE/File Associations/procedure_dde.png | Bin 0 -> 6350 bytes .../Graphics/FSE/File Associations/tdp_dde.ico | Bin 0 -> 109508 bytes .../Graphics/FSE/File Associations/tdp_dde.png | Bin 0 -> 7337 bytes .../Graphics/FSE/File Associations/tfp_dde.ico | Bin 0 -> 105372 bytes .../Graphics/FSE/File Associations/tfp_dde.png | Bin 0 -> 4111 bytes .../Graphics/FSE/File Associations/tup_dde.ico | Bin 0 -> 106375 bytes .../Graphics/FSE/File Associations/tup_dde.png | Bin 0 -> 5048 bytes .../Advanced Installer Projects/FSE Installer.aip | 20 ++- .../ViewModels/DiagnosticsViewVM.cs | 35 ++++++ .../Help/proc-doc.chm | Bin 206257 -> 212099 bytes .../Tango.FSE.Procedures.Documentation.shfbproj | 1 + .../Navigation/RunProcedureNavigationObject.cs | 1 + .../ViewModels/ProcedureDesignerViewVM.cs | 39 +++++- .../ViewModels/ProcedureRunnerViewVM.cs | 60 ++++++--- .../ViewModels/FirmwareUpgradeGeneratedViewVM.cs | 40 +++++- .../Views/FirmwareUpgradeView.xaml | 2 +- .../FSEApplication/IFSEApplicationManager.cs | 5 + .../FSE/Tango.FSE.Common/FSESettings.cs | 6 + .../FSE/Tango.FSE.Common/FSEViewModel.cs | 7 ++ .../FileAssociation/FileAssociationPackage.cs | 1 + .../FileAssociation/IFileAssociationProvider.cs | 3 +- .../Navigation/INavigationManager.cs | 5 +- .../Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs | 46 +++++-- .../FSEApplication/DefaultFSEApplicationManager.cs | 11 ++ .../DefaultFileAssociationHandler.cs | 24 ---- .../DefaultFileAssociationProvider.cs | 136 +++++++++++++++++++++ .../Navigation/DefaultNavigationManager.cs | 10 +- .../FSE/Tango.FSE.UI/Tango.FSE.UI.csproj | 5 +- .../FSE/Tango.FSE.UI/ViewModelLocator.cs | 4 + .../FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs | 8 ++ .../Visual_Studio/FSE/Tango.FSE.UI/packages.config | 1 + .../Controllers/FSEController.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- 34 files changed, 406 insertions(+), 68 deletions(-) create mode 100644 Software/Graphics/FSE/File Associations/procedure_dde.ico create mode 100644 Software/Graphics/FSE/File Associations/procedure_dde.png create mode 100644 Software/Graphics/FSE/File Associations/tdp_dde.ico create mode 100644 Software/Graphics/FSE/File Associations/tdp_dde.png create mode 100644 Software/Graphics/FSE/File Associations/tfp_dde.ico create mode 100644 Software/Graphics/FSE/File Associations/tfp_dde.png create mode 100644 Software/Graphics/FSE/File Associations/tup_dde.ico create mode 100644 Software/Graphics/FSE/File Associations/tup_dde.png delete mode 100644 Software/Visual_Studio/FSE/Tango.FSE.UI/FileAssociation/DefaultFileAssociationHandler.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.UI/FileAssociation/DefaultFileAssociationProvider.cs (limited to 'Software/Visual_Studio/Web/Tango.MachineService') diff --git a/Software/Graphics/FSE/File Associations/procedure_dde.ico b/Software/Graphics/FSE/File Associations/procedure_dde.ico new file mode 100644 index 000000000..7df42ce47 Binary files /dev/null and b/Software/Graphics/FSE/File Associations/procedure_dde.ico differ diff --git a/Software/Graphics/FSE/File Associations/procedure_dde.png b/Software/Graphics/FSE/File Associations/procedure_dde.png new file mode 100644 index 000000000..1e92440d6 Binary files /dev/null and b/Software/Graphics/FSE/File Associations/procedure_dde.png differ diff --git a/Software/Graphics/FSE/File Associations/tdp_dde.ico b/Software/Graphics/FSE/File Associations/tdp_dde.ico new file mode 100644 index 000000000..a81e68d65 Binary files /dev/null and b/Software/Graphics/FSE/File Associations/tdp_dde.ico differ diff --git a/Software/Graphics/FSE/File Associations/tdp_dde.png b/Software/Graphics/FSE/File Associations/tdp_dde.png new file mode 100644 index 000000000..9ba449028 Binary files /dev/null and b/Software/Graphics/FSE/File Associations/tdp_dde.png differ diff --git a/Software/Graphics/FSE/File Associations/tfp_dde.ico b/Software/Graphics/FSE/File Associations/tfp_dde.ico new file mode 100644 index 000000000..27ce70914 Binary files /dev/null and b/Software/Graphics/FSE/File Associations/tfp_dde.ico differ diff --git a/Software/Graphics/FSE/File Associations/tfp_dde.png b/Software/Graphics/FSE/File Associations/tfp_dde.png new file mode 100644 index 000000000..0577cfb13 Binary files /dev/null and b/Software/Graphics/FSE/File Associations/tfp_dde.png differ diff --git a/Software/Graphics/FSE/File Associations/tup_dde.ico b/Software/Graphics/FSE/File Associations/tup_dde.ico new file mode 100644 index 000000000..013e33ba5 Binary files /dev/null and b/Software/Graphics/FSE/File Associations/tup_dde.ico differ diff --git a/Software/Graphics/FSE/File Associations/tup_dde.png b/Software/Graphics/FSE/File Associations/tup_dde.png new file mode 100644 index 000000000..9c6374f87 Binary files /dev/null and b/Software/Graphics/FSE/File Associations/tup_dde.png differ diff --git a/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip b/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip index 4d7250d8e..901fd1a05 100644 --- a/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip +++ b/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip @@ -310,6 +310,7 @@ + @@ -666,6 +667,7 @@ + @@ -810,6 +812,9 @@ + + + @@ -1078,11 +1083,15 @@ + - + + + + @@ -1139,7 +1148,10 @@ - + + + + @@ -1166,6 +1178,10 @@ + + + + diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs index ac9279ab8..8a89fbc8f 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs @@ -15,8 +15,10 @@ using Tango.BL.Enumerations; using Tango.Core.Commands; using Tango.FSE.Common; using Tango.FSE.Common.Diagnostics; +using Tango.FSE.Common.FileAssociation; using Tango.FSE.Common.Notifications; using Tango.FSE.Diagnostics.Project; +using Tango.FSE.Diagnostics.Views; using Tango.PMR.Diagnostics; namespace Tango.FSE.Diagnostics.ViewModels @@ -403,6 +405,8 @@ namespace Tango.FSE.Diagnostics.ViewModels { base.OnApplicationStarted(); DiagnosticsProvider.FrameReceived += DiagnosticsProvider_FrameReceived; + + FileAssociationProvider.RegisterFileAssociationHandler("diagnostics", HandleDiagnosticsFileAssociation); } public async override void OnApplicationReady() @@ -781,5 +785,36 @@ namespace Tango.FSE.Diagnostics.ViewModels } #endregion + + #region File Association + + private async void HandleDiagnosticsFileAssociation(FileAssociationPackage package) + { + if (!CurrentUser.HasPermission(Permissions.FSE_EditDiagnosticsProject)) + { + await NotificationProvider.ShowError("Current user profile does not allow loading custom diagnostics projects."); + return; + } + + if (File.Exists(package.File)) + { + try + { + LogManager.Log("Opening diagnostics project from file association..."); + await NavigationManager.NavigateTo(true, nameof(DiagnosticsView)); + using (NotificationProvider.PushTaskItem("Loading diagnostics project...")) + { + await Task.Delay(2000); + await LoadProject(package.File); + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error occurred while trying to handle the diagnostics file association."); + } + } + } + + #endregion } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chm b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chm index 861555098..1fb821112 100644 Binary files a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chm and b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chm differ diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Tango.FSE.Procedures.Documentation.shfbproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Tango.FSE.Procedures.Documentation.shfbproj index 7a0935061..abb8a83f9 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Tango.FSE.Procedures.Documentation.shfbproj +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Tango.FSE.Procedures.Documentation.shfbproj @@ -80,6 +80,7 @@ + diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Navigation/RunProcedureNavigationObject.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Navigation/RunProcedureNavigationObject.cs index b91d6ca03..c19857c21 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Navigation/RunProcedureNavigationObject.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Navigation/RunProcedureNavigationObject.cs @@ -9,5 +9,6 @@ namespace Tango.FSE.Procedures.Navigation public class RunProcedureNavigationObject { public ProcedureProject Project { get; set; } + public bool StartProcedure { get; set; } } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureDesignerViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureDesignerViewVM.cs index 34510e54c..e9c476a20 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureDesignerViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureDesignerViewVM.cs @@ -21,6 +21,7 @@ using Tango.Core.Commands; using Tango.Core.ExtensionMethods; using Tango.Core.Helpers; using Tango.FSE.Common; +using Tango.FSE.Common.FileAssociation; using Tango.FSE.Common.Navigation; using Tango.FSE.Common.Notifications; using Tango.FSE.Procedures.Contracts; @@ -454,6 +455,8 @@ namespace Tango.FSE.Procedures.ViewModels LogManager.Log(ex, "Error generating procedure designer auto creation groups."); } }); + + FileAssociationProvider.RegisterFileAssociationHandler("designer", HandlerProcedureFileAssociation); } public override void OnNavigatedTo() @@ -658,7 +661,8 @@ namespace Tango.FSE.Procedures.ViewModels { await NavigationManager.NavigateWithObject(new RunProcedureNavigationObject() { - Project = Project + Project = Project, + StartProcedure = true }); } } @@ -907,6 +911,12 @@ namespace Tango.FSE.Procedures.ViewModels private void OpenProject(String file) { + if (Project != null && Project.IsRunning) + { + NotificationProvider.ShowError("Cannot load a project while another project is running."); + return; + } + try { Project = ProcedureProject.FromJson(File.ReadAllText(file)); @@ -1517,5 +1527,32 @@ namespace Tango.FSE.Procedures.ViewModels } #endregion + + #region File Association + + private void HandlerProcedureFileAssociation(FileAssociationPackage package) + { + if (!CurrentUser.HasPermission(Permissions.FSE_RunProcedureDesigner)) + { + NotificationProvider.ShowError("Current user profile does not allow running the procedure designer."); + return; + } + + if (File.Exists(package.File)) + { + try + { + LogManager.Log("Opening procedure project from file association..."); + NavigationManager.NavigateTo(true, nameof(ProcedureDesignerView)); + OpenProject(package.File); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error occurred while trying to handle the procedure file association."); + } + } + } + + #endregion } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureRunnerViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureRunnerViewVM.cs index d69ba63f8..6ccc77669 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureRunnerViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureRunnerViewVM.cs @@ -1,19 +1,14 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.ComponentModel; +using System.IO; using System.Linq; -using System.Reflection; -using System.Text; using System.Threading.Tasks; using Tango.BL.Entities; using Tango.Core; using Tango.Core.Commands; -using Tango.CSV; using Tango.FSE.Common; +using Tango.FSE.Common.FileAssociation; using Tango.FSE.Common.Navigation; -using Tango.FSE.Procedures.CSV; -using Tango.FSE.Procedures.Dialogs; using Tango.FSE.Procedures.Messages; using Tango.FSE.Procedures.Navigation; using Tango.FSE.Procedures.Views; @@ -29,8 +24,8 @@ namespace Tango.FSE.Procedures.ViewModels } private bool _requiresReloadingOfProjects; - private bool _isFromDesigner; - private ProcedureProject _designerProject; + private bool _isFromNavigation; + private RunProcedureNavigationObject _navigationObject; private RunnerView _selectedView; public RunnerView SelectedView @@ -121,6 +116,13 @@ namespace Tango.FSE.Procedures.ViewModels RegisterForMessage((x) => _requiresReloadingOfProjects = true); } + public override void OnApplicationStarted() + { + base.OnApplicationStarted(); + + FileAssociationProvider.RegisterFileAssociationHandler("procedure", HandlerProcedureFileAssociation); + } + private async void StartProject() { try @@ -192,18 +194,22 @@ namespace Tango.FSE.Procedures.ViewModels LoadPublishedProcedureProjects(); } - if (_isFromDesigner) + if (_isFromNavigation) { if (!IsRunning) { - RunningProcedureProject = _designerProject; + RunningProcedureProject = _navigationObject.Project; RaisePropertyChanged(nameof(HasProcedureInputs)); ProjectRunner = new ProjectRunner(RunningProcedureProject); ProjectRunner.StateChanged += (x, e) => InvalidateRelayCommands(); Status = "Ready"; InvalidateRelayCommands(); SelectedView = RunnerView.ProcedureRunnerExecutionView; - StartProject(); + + if (_navigationObject.StartProcedure) + { + StartProject(); + } } else { @@ -252,16 +258,16 @@ namespace Tango.FSE.Procedures.ViewModels { SelectedView = RunnerView.ProcedureRunnerCatalogView; - if (_isFromDesigner) + if (_isFromNavigation) { - _isFromDesigner = false; + _isFromNavigation = false; return Task.FromResult(true); } return Task.FromResult(false); } - _isFromDesigner = false; + _isFromNavigation = false; return base.OnNavigateBackRequest(); } @@ -283,8 +289,28 @@ namespace Tango.FSE.Procedures.ViewModels public void OnNavigatedToWithObject(RunProcedureNavigationObject obj) { - _isFromDesigner = true; - _designerProject = obj.Project; + _isFromNavigation = true; + _navigationObject = obj; + } + + private async void HandlerProcedureFileAssociation(FileAssociationPackage package) + { + if (File.Exists(package.File)) + { + try + { + ProcedureProject project = ProcedureProject.FromJson(File.ReadAllText(package.File)); + LogManager.Log("Loading procedure from file association..."); + await NavigationManager.NavigateWithObject(new RunProcedureNavigationObject() + { + Project = project + }); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error occurred while trying to handler the procedure file association."); + } + } } } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/FirmwareUpgradeGeneratedViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/FirmwareUpgradeGeneratedViewVM.cs index accc8d111..ce01b5804 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/FirmwareUpgradeGeneratedViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/FirmwareUpgradeGeneratedViewVM.cs @@ -5,10 +5,13 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.BL.Entities; +using Tango.BL.Enumerations; using Tango.Core.Commands; using Tango.FSE.Common; +using Tango.FSE.Common.FileAssociation; using Tango.FSE.Common.Navigation; using Tango.FSE.Common.RemoteUpgrade; +using Tango.FSE.Upgrade.Views; using static Tango.FSE.Upgrade.ViewModels.FirmwareUpgradeGeneratedViewVM; namespace Tango.FSE.Upgrade.ViewModels @@ -102,6 +105,8 @@ namespace Tango.FSE.Upgrade.ViewModels base.OnApplicationStarted(); MachineProvider.MachineConnected += (_, __) => InvalidateCanUpgradeNow(); MachineProvider.MachineDisconnected += (_, __) => InvalidateCanUpgradeNow(); + + FileAssociationProvider.RegisterFileAssociationHandler("tfp", HandleTfpFileAssociation); } private void InvalidateCanUpgradeNow() @@ -199,7 +204,6 @@ namespace Tango.FSE.Upgrade.ViewModels IsCompleted = false; SelectedVersion = null; IsUpgradeNowSelected = true; - TfpFileLocation = null; InvalidateRelayCommands(); } @@ -235,5 +239,39 @@ namespace Tango.FSE.Upgrade.ViewModels return true; } + + private void HandleTfpFileAssociation(FileAssociationPackage package) + { + if (!IsFree) + { + NotificationProvider.ShowError("Cannot perform firmware upgrade while another upgrade is running."); + return; + } + + if (!CurrentUser.HasPermission(Permissions.FSE_RemoteUpgradeOnline)) + { + NotificationProvider.ShowError("Current user profile does not allow online remote upgrade."); + return; + } + + if (File.Exists(package.File)) + { + try + { + LogManager.Log("Performing remote firmware upgrade from file association..."); + Handler = new RemoteUpgradeHandler("Ready"); + IsCompleted = false; + TfpFileLocation = package.File; + IsUsingExistingTfp = true; + InvalidateCanUpgradeNow(); + NavigationManager.NavigateTo(true); + ModularNavigationManager.NavigateTo(Navigation.RemoteUpgradeView.FirmwareUpgradeGeneratedView); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error occurred while trying to handle the tfp file association."); + } + } + } } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml index 6aeb0fcb1..3e93300c0 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml @@ -60,7 +60,7 @@ - + I already have the .tfp file and just want to upgrade the currently connected machine. (requires an active machine connection) diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEApplication/IFSEApplicationManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEApplication/IFSEApplicationManager.cs index c3f54d0e2..5f72fbd29 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEApplication/IFSEApplicationManager.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEApplication/IFSEApplicationManager.cs @@ -63,6 +63,11 @@ namespace Tango.FSE.Common.FSEApplication /// void Restart(); + /// + /// Activates the main window if it's not in focus. + /// + void ActivateMainWindow(); + /// /// Gets the application version. /// diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSESettings.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSESettings.cs index 352294e0a..c85a5fd35 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSESettings.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSESettings.cs @@ -141,6 +141,11 @@ namespace Tango.FSE.Common /// public bool TerminatedExpectedly { get; set; } + /// + /// Gets or sets the file association service port. + /// + public int FileAssociationServicePort { get; set; } + /// /// Initializes a new instance of the class. /// @@ -158,6 +163,7 @@ namespace Tango.FSE.Common AutoCheckForUpdates = true; EnableAdaptiveScaling = true; TerminatedExpectedly = true; + FileAssociationServicePort = 1800; } } } \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs index d6e3a5b52..07d2a7a5b 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs @@ -43,6 +43,7 @@ using Tango.FSE.Common.Tiles; using Tango.FSE.Common.RemoteJob; using Tango.FSE.Common.WindowsManager; using Tango.FSE.Common.DemoMode; +using Tango.FSE.Common.FileAssociation; namespace Tango.FSE.Common { @@ -228,6 +229,12 @@ namespace Tango.FSE.Common [TangoInject] public IDemoModeManager DemoModeManager { get; set; } + /// + /// Gets or sets the file association provider. + /// + [TangoInject] + public IFileAssociationProvider FileAssociationProvider { get; set; } + /// /// Gets or sets the FSE service. /// diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/FileAssociationPackage.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/FileAssociationPackage.cs index 106c37f16..ec072e7b1 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/FileAssociationPackage.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/FileAssociationPackage.cs @@ -8,6 +8,7 @@ namespace Tango.FSE.Common.FileAssociation { public class FileAssociationPackage { + public String TargetName { get; set; } public String File { get; set; } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/IFileAssociationProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/IFileAssociationProvider.cs index 6b4440f41..2517ba82c 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/IFileAssociationProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/IFileAssociationProvider.cs @@ -6,8 +6,9 @@ using System.Threading.Tasks; namespace Tango.FSE.Common.FileAssociation { - public interface IFileAssociationProvider + public interface IFileAssociationProvider : INotifyApplicationStarted, INotifyApplicationReady { + bool HasStartArgsPackage { get; } void RegisterFileAssociationHandler(String targetName, Action handler); } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Navigation/INavigationManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Navigation/INavigationManager.cs index ddcc5dc8f..2efd3c75d 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Navigation/INavigationManager.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Navigation/INavigationManager.cs @@ -106,9 +106,10 @@ namespace Tango.FSE.Common.Navigation /// The type of the view. /// The type of the pass. /// The object. - /// if set to true [push to history]. + /// Push the current view to history ?. + /// Force the navigation even if we are on the same view. /// - Task NavigateWithObject(TPass obj, bool pushToHistory = true) + Task NavigateWithObject(TPass obj, bool pushToHistory = true, bool force = false) where TModule : IFSEModule; /// diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs index 196978f69..de0594703 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs @@ -1,4 +1,5 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; using System.Configuration; using System.Data; @@ -14,11 +15,14 @@ using Tango.Core.DI; using Tango.Core.Helpers; using Tango.FSE.Common; using Tango.FSE.Common.BugReporting; +using Tango.FSE.Common.FileAssociation; using Tango.FSE.Common.Helpers; using Tango.FSE.Common.Notifications; +using Tango.FSE.UI.FileAssociation; using Tango.Integration.Operation; using Tango.Logging; using Tango.Settings; +using ZetaIpc.Runtime.Client; namespace Tango.FSE.UI { @@ -51,26 +55,42 @@ namespace Tango.FSE.UI protected override void OnStartup(StartupEventArgs e) { - if (e.Args != null) + try { - if (e.Args.Length == 3) + if (e.Args != null) { - if (e.Args[0] == "-file") + if (e.Args.Length == DefaultFileAssociationProvider.FILE_ASSOCIATION_ARGS_COUNT) { - if (mutex.WaitOne(TimeSpan.Zero, true)) - { - mutex.ReleaseMutex(); - MessageBox.Show($"Run Procedure {e.Args[2]} on this instance."); - } - else + if (e.Args[0] == DefaultFileAssociationProvider.FILE_ASSOCIATION_PREFIX) { - MessageBox.Show($"Run Procedure {e.Args[2]} on another instance."); - Environment.Exit(0); - return; + if (mutex.WaitOne(TimeSpan.Zero, true)) + { + //This is the first instance. Do nothing... + mutex.ReleaseMutex(); + } + else + { + //MessageBox.Show($"Run Procedure {e.Args[2]} on another instance."); + var settings = SettingsManager.Default.GetOrCreate(); + var ipcClient = new IpcClient(); + ipcClient.Initialize(settings.FileAssociationServicePort); + ipcClient.Send(JsonConvert.SerializeObject(new FileAssociationPackage() + { + TargetName = e.Args[1], + File = e.Args[2] + })); + Thread.Sleep(1000); + Environment.Exit(0); + return; + } } } } } + catch (Exception ex) + { + Debug.WriteLine(ex); + } //Set culture info. var enUSCulture = new CultureInfo("en-US"); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/FSEApplication/DefaultFSEApplicationManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/FSEApplication/DefaultFSEApplicationManager.cs index 48087bff9..aa5d4a629 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/FSEApplication/DefaultFSEApplicationManager.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/FSEApplication/DefaultFSEApplicationManager.cs @@ -457,5 +457,16 @@ namespace Tango.FSE.UI.FSEApplication return StartupArgs.Contains("-demo"); } } + + /// + /// Activates the main window if it's not in focus. + /// + public void ActivateMainWindow() + { + MainWindow.Instance.Dispatcher.BeginInvoke(new Action(() => + { + MainWindow.Instance.Activate(); + })); + } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileAssociation/DefaultFileAssociationHandler.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileAssociation/DefaultFileAssociationHandler.cs deleted file mode 100644 index 88f4fff05..000000000 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileAssociation/DefaultFileAssociationHandler.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.FSE.Common.FileAssociation; - -namespace Tango.FSE.UI.FileAssociation -{ - public class DefaultFileAssociationHandler : IFileAssociationProvider - { - private Dictionary> _handlers; - - public DefaultFileAssociationHandler() - { - _handlers = new Dictionary>(); - } - - public void RegisterFileAssociationHandler(string targetName, Action handler) - { - _handlers.Add(targetName.ToLower(), handler); - } - } -} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileAssociation/DefaultFileAssociationProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileAssociation/DefaultFileAssociationProvider.cs new file mode 100644 index 000000000..9e2997e92 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileAssociation/DefaultFileAssociationProvider.cs @@ -0,0 +1,136 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.DI; +using Tango.FSE.Common; +using Tango.FSE.Common.FileAssociation; +using Tango.FSE.Common.FSEApplication; +using Tango.FSE.Common.Threading; +using Tango.Logging; +using ZetaIpc.Runtime.Server; + +namespace Tango.FSE.UI.FileAssociation +{ + [TangoCreateWhenRegistered] + public class DefaultFileAssociationProvider : FSEExtendedObject, IFileAssociationProvider + { + private Dictionary> _handlers; + private IpcServer _ipcServer; + + public const string FILE_ASSOCIATION_PREFIX = "-file"; + public const int FILE_ASSOCIATION_ARGS_COUNT = 3; + + public bool HasStartArgsPackage { get; private set; } + + [TangoInject] + private IDispatcherProvider DispatcherProvider { get; set; } + + [TangoInject] + private IFSEApplicationManager ApplicationManager { get; set; } + + public DefaultFileAssociationProvider() + { + _handlers = new Dictionary>(); + _ipcServer = new IpcServer(); + } + + public void RegisterFileAssociationHandler(string targetName, Action handler) + { + _handlers.Add(targetName.ToLower(), handler); + } + + public async void OnApplicationReady(IFSEApplicationManager applicationManager) + { + try + { + LogManager.Log("Starting file association IPC service..."); + _ipcServer.Start(Settings.FileAssociationServicePort); + _ipcServer.ReceivedRequest += _ipcServer_ReceivedRequest; + } + catch (Exception ex) + { + LogManager.Log(ex, "Error starting file association IPC service. Another instance of the application might already be running..."); + } + + var args = applicationManager.StartupArgs; + + LogManager.Log("Processing file association if any..."); + + if (args.Count == FILE_ASSOCIATION_ARGS_COUNT) + { + if (args[0] == FILE_ASSOCIATION_PREFIX) + { + + //This delay is a workaround for when the invoked handler navigates to some module. + //The navigation system does not catches the navigation request properly... :/ + await Task.Delay(500); + + LogManager.Log($"File association package found: '{String.Join(" ", args)}'. Invoking handler..."); + + try + { + String targetName = args[1].ToLower(); + + if (_handlers.ContainsKey(targetName)) + { + var package = new FileAssociationPackage() + { + TargetName = targetName, + File = args[2] + }; + + _handlers[targetName].Invoke(package); + } + else + { + LogManager.Log("File association handler not found.", LogCategory.Warning); + } + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error invoking file association handler for package '{String.Join(" ", args)}'."); + } + } + } + } + + private void _ipcServer_ReceivedRequest(object sender, ReceivedRequestEventArgs e) + { + try + { + e.Handled = true; + LogManager.Log($"File association package received through IPC server.\n{e.Request}\nInvoking handler..."); + + var package = JsonConvert.DeserializeObject(e.Request); + + if (_handlers.ContainsKey(package.TargetName.ToLower())) + { + DispatcherProvider.Invoke(() => + { + ApplicationManager.ActivateMainWindow(); + _handlers[package.TargetName.ToLower()].Invoke(package); + }); + } + else + { + LogManager.Log($"Handler not found for target '{package.TargetName}'.", LogCategory.Warning); + } + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error invoking file association handler."); + } + } + + public void OnApplicationStarted(IFSEApplicationManager applicationManager) + { + HasStartArgsPackage = + applicationManager.StartupArgs.Count == FILE_ASSOCIATION_ARGS_COUNT + && + applicationManager.StartupArgs[0] == FILE_ASSOCIATION_PREFIX; + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Navigation/DefaultNavigationManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Navigation/DefaultNavigationManager.cs index 9de496793..7a55b085a 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Navigation/DefaultNavigationManager.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Navigation/DefaultNavigationManager.cs @@ -44,6 +44,7 @@ namespace Tango.FSE.UI.Navigation private Object _currentVM; private String _lastFullPath; private bool _preventHistory; + private bool _force; private Stack _navigationHistory; @@ -242,7 +243,7 @@ namespace Tango.FSE.UI.Navigation { try { - if (_lastFullPath == fullPath) + if (_lastFullPath == fullPath && !_force) { return true; } @@ -450,12 +451,15 @@ namespace Tango.FSE.UI.Navigation /// The type of the view. /// The type of the pass. /// The object. - /// if set to true [push to history]. + /// Push the current view to history ?. + /// Force the navigation even if we are on the same view. /// - public Task NavigateWithObject(TPass obj, bool pushToHistory = true) where TModule : IFSEModule + public Task NavigateWithObject(TPass obj, bool pushToHistory = true, bool force = false) where TModule : IFSEModule { + _force = true; return NavigateTo(typeof(TModule).Name + "." + typeof(TView).Name, pushToHistory, (fromVM, toVM) => { + _force = false; if (toVM is INavigationObjectReceiver) { (toVM as INavigationObjectReceiver).OnNavigatedToWithObject(obj); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj index 44a163326..3d5fa6db1 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj @@ -200,6 +200,9 @@ + + ..\..\packages\ZetaIpc.1.0.0.9\lib\netstandard2.0\ZetaIpc.dll + @@ -271,7 +274,7 @@ - + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs index 13520ec7e..25d0b45c9 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs @@ -64,6 +64,8 @@ using Tango.FSE.Common.DemoMode; using Tango.FSE.UI.DemoMode; using Tango.FSE.Common.SQL; using Tango.FSE.UI.SQL; +using Tango.FSE.Common.FileAssociation; +using Tango.FSE.UI.FileAssociation; namespace Tango.FSE.UI { @@ -101,6 +103,7 @@ namespace Tango.FSE.UI TangoIOC.Default.Unregister(); TangoIOC.Default.Unregister(); TangoIOC.Default.Unregister(); + TangoIOC.Default.Unregister(); //TangoIOC.Default.Unregister(); //TangoIOC.Default.Unregister(); //TangoIOC.Default.Unregister(); @@ -138,6 +141,7 @@ namespace Tango.FSE.UI TangoIOC.Default.Register(); TangoIOC.Default.Register(); TangoIOC.Default.Register(); + TangoIOC.Default.Register(); TangoIOC.Default.Register(); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs index 5c4f1b11a..9a5433f82 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs @@ -232,6 +232,14 @@ namespace Tango.FSE.UI.ViewModels { this.SetFocus(() => Password); } + + if (RememberMe) + { + if (FileAssociationProvider.HasStartArgsPackage) + { + Login(); + } + } } /// diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config b/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config index d0abb0ebf..4fda0a885 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config @@ -68,4 +68,5 @@ + \ No newline at end of file diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs index 387430f89..b9dacfcf9 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs @@ -200,7 +200,7 @@ namespace Tango.MachineService.Controllers String comments = String.Join(Environment.NewLine, versions.OrderBy(x => Version.Parse(x.Version)).Where(x => Version.Parse(x.Version) > currentVersion).Select(x => x.Comments)); - if (latestVersion != null && Version.Parse(latestVersion.Version) != currentVersion) + if (latestVersion != null && Version.Parse(latestVersion.Version) > currentVersion) { var manager = new BlobStorageManager(); var container = manager.GetContainer(MachineServiceConfig.FSE_VERSIONS_CONTAINER); diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs index a6aa93dee..704da0c08 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs @@ -24,4 +24,4 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("3.0.1.0")] +[assembly: AssemblyVersion("3.0.2.0")] -- cgit v1.3.1 From 4e216a0ca8ad3608b845fa445b73034e1a67b8af Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Wed, 19 Aug 2020 01:45:02 +0300 Subject: DB: Changed TechMonitors HeadZone5_6HeaterCurrent => HeadZone56HeaterCurrent Working on insights and insights annotations. Added insights events. Added insights settings to PPC advanced settings. Added compression support for transport adapters. Implemented compression support on TCP/SignalR/WebRTC. Added Compression flag to ExternalBridge discovery packet. Added compression setting to PPC advanced settings. Refactored transport layer to use Bson instead of Json for Generic Messages. Added all SciChart referenced assemblies. Registered EF Extensions license for FSE. Added support for FSE PushTask notification cancel button. --- Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 22675456 -> 22675456 bytes .../Messages/Diagnostics/DiagnosticsMonitors.proto | 2 +- .../PMR/Messages/Insights/InsightsMonitors.proto | 2 +- .../ExternalBridgeUdpDiscoveryPacket.proto | 1 + .../Tango.FSE.Insights/Contracts/IInsightsView.cs | 14 + .../Tango.FSE.Insights/SciChart/InsightsChart.cs | 68 + .../SciChart/InsightsRubberBandXYZoomModifier.cs | 24 + .../SciChart/InsightsZoomPanModifier.cs | 22 + .../Tango.FSE.Insights/Tango.FSE.Insights.csproj | 40 + .../Modules/Tango.FSE.Insights/Themes/Generic.xaml | 60 + .../ViewModels/InsightsViewVM.cs | 470 +- .../Tango.FSE.Insights/Views/InsightsView.xaml | 263 +- .../Tango.FSE.Insights/Views/InsightsView.xaml.cs | 30 +- .../EntityFrameworkExtensionsHelper.cs | 22 + .../FSE/Tango.FSE.BL/Tango.FSE.BL.csproj | 1 + .../FSE/Tango.FSE.Common/FSEViewModel.cs | 7 + .../FileSystem/IFileSystemProvider.cs | 14 +- .../Tango.FSE.Common/Insights/IInsightsProvider.cs | 13 + .../Tango.FSE.Common/Insights/InsightsHandler.cs | 103 + .../Insights/InsightsHandlerStatus.cs | 18 + .../Tango.FSE.Common/Insights/InsightsPackage.cs | 22 + .../Insights/InsightsReadyEvent.cs | 20 + .../Insights/InsightsReadyFrame.cs | 27 + .../Notifications/INotificationProvider.cs | 4 +- .../FSE/Tango.FSE.Common/Notifications/TaskItem.cs | 11 +- .../FSE/Tango.FSE.Common/Resources/Converters.xaml | 1 + .../FSE/Tango.FSE.Common/Tango.FSE.Common.csproj | 39 + Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml | 13 + .../Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs | 20 + .../Connection/DefaultMachineProvider.cs | 4 +- .../Controls/NotificationsControl.xaml | 2 +- .../FileSystem/DefaultFileSystemProvider.cs | 40 +- .../Insights/DefaultInsightsProvider.cs | 136 + .../Notifications/DefaultNotificationProvider.cs | 17 +- .../Tango.FSE.UI/Panes/ConnectedMachinePane.xaml | 2 + .../FSE/Tango.FSE.UI/Tango.FSE.UI.csproj | 33 + .../FSE/Tango.FSE.UI/ViewModelLocator.cs | 4 + .../Tango.PPC.MachineSettings/Views/MainView.xaml | 27 +- .../ExternalBridge/PPCExternalBridgeService.cs | 1 + .../FileSystem/DefaultFileSystemService.cs | 8 +- .../Insights/DefaultInsightsService.cs | 3 + .../PPC/Tango.PPC.Common/PPCSettings.cs | 6 + .../PPC/Tango.PPC.Common/Resources/Merged.xaml | 1 + .../SciChart/SciChart.Charting.DrawingTools.dll | Bin 0 -> 184832 bytes .../SciChart/SciChart.Charting.DrawingTools.xml | 1189 + .../SciChart/SciChart.Charting.dll | Bin 0 -> 2637312 bytes .../SciChart/SciChart.Charting.xml | 36951 +++++++++++++++++++ .../SciChart/SciChart.Charting3D.dll | Bin 0 -> 9101312 bytes .../SciChart/SciChart.Charting3D.xml | 13485 +++++++ .../SciChart/SciChart.Core.dll | Bin 0 -> 2162688 bytes .../SciChart/SciChart.Core.xml | 2968 ++ .../SciChart/SciChart.Data.dll | Bin 0 -> 17156608 bytes .../SciChart/SciChart.Data.xml | 2292 ++ .../SciChart/SciChart.Drawing.DirectX.dll | Bin 0 -> 230400 bytes .../SciChart/SciChart.Drawing.DirectX.xml | 274 + .../SciChart/SciChart.Drawing.dll | Bin 0 -> 953344 bytes .../SciChart/SciChart.Drawing.xml | 3370 ++ .../SciChart.Examples.ExternalDependencies.dll | Bin 0 -> 8861696 bytes .../SciChart.Examples.ExternalDependencies.xml | 388 + .../SciChart/SharpDX.D3DCompiler.dll | Bin 0 -> 58880 bytes .../SciChart/SharpDX.DXGI.dll | Bin 0 -> 148480 bytes .../SciChart/SharpDX.Direct3D11.Effects.dll | Bin 0 -> 58880 bytes .../SciChart/SharpDX.Direct3D11.dll | Bin 0 -> 283136 bytes .../SciChart/SharpDX.Direct3D9.dll | Bin 0 -> 338944 bytes .../SciChart/SharpDX.Mathematics.dll | Bin 0 -> 215552 bytes .../Referenced Assemblies/SciChart/SharpDX.dll | Bin 0 -> 274944 bytes .../SciChart/sharpdx_direct3d11_1_effects_x64.dll | Bin 0 -> 358912 bytes .../SciChart/sharpdx_direct3d11_1_effects_x86.dll | Bin 0 -> 298496 bytes .../Tango.BL/Enumerations/TechMonitors.cs | 2 +- .../ExternalBridge/EmulatorExternalBridge.cs | 2 + .../Visual_Studio/Tango.Insights/InsightsEvent.cs | 14 + .../Visual_Studio/Tango.Insights/InsightsFile.cs | 3 + .../Visual_Studio/Tango.Insights/InsightsFrame.cs | 4 +- .../Tango.Insights/InsightsListener.cs | 95 +- .../Tango.Insights/InsightsManager.cs | 29 +- .../Tango.Insights/Tango.Insights.csproj | 12 + .../ExternalBridge/ExternalBridgeScanner.cs | 6 +- .../ExternalBridge/ExternalBridgeService.cs | 8 + .../ExternalBridge/ExternalBridgeSignalRClient.cs | 14 +- .../ExternalBridge/ExternalBridgeTcpClient.cs | 21 +- .../ExternalBridge/ExternalBridgeUsbClient.cs | 5 + .../ExternalBridge/IExternalBridgeClient.cs | 5 + .../ExternalBridge/IExternalBridgeService.cs | 5 + .../ExternalBridge/Web/MachineInfo.cs | 1 + .../Tango.PMR/Diagnostics/DiagnosticsMonitors.cs | 48 +- .../Tango.PMR/Insights/InsightsMonitors.cs | 46 +- .../ExternalBridgeUdpDiscoveryPacket.cs | 35 +- .../Converters/TimeSpanToDaysConverter.cs | 23 + .../Tango.SharedUI/Tango.SharedUI.csproj | 3 +- .../Adapters/SignalRTransportAdapter.cs | 9 +- .../Adapters/TcpTransportAdapter.cs | 11 + .../Tango.Transport/Compression/GZipHelper.cs | 42 + .../Tango.Transport/GenericMessageSerializer.cs | 64 +- .../Tango.Transport/ITransportAdapter.cs | 5 + .../Tango.Transport/Tango.Transport.csproj | 3 +- .../Tango.Transport/TransportAdapterBase.cs | 5 + .../Tango.WebRTC/WebRtcTransportAdapter.cs | 16 +- .../Properties/AssemblyInfo.cs | 2 +- 99 files changed, 62906 insertions(+), 164 deletions(-) create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Contracts/IInsightsView.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsChart.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsRubberBandXYZoomModifier.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsZoomPanModifier.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Themes/Generic.xaml create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.BL/EntityFrameworkExtensionsHelper.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/IInsightsProvider.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsHandler.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsHandlerStatus.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsPackage.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsReadyEvent.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsReadyFrame.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Charting.DrawingTools.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Charting.DrawingTools.xml create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Charting.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Charting.xml create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Charting3D.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Charting3D.xml create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Core.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Core.xml create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Data.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Data.xml create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Drawing.DirectX.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Drawing.DirectX.xml create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Drawing.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Drawing.xml create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Examples.ExternalDependencies.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SciChart.Examples.ExternalDependencies.xml create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SharpDX.D3DCompiler.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SharpDX.DXGI.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SharpDX.Direct3D11.Effects.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SharpDX.Direct3D11.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SharpDX.Direct3D9.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SharpDX.Mathematics.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/SharpDX.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/sharpdx_direct3d11_1_effects_x64.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SciChart/sharpdx_direct3d11_1_effects_x86.dll create mode 100644 Software/Visual_Studio/Tango.Insights/InsightsEvent.cs create mode 100644 Software/Visual_Studio/Tango.SharedUI/Converters/TimeSpanToDaysConverter.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/GZipHelper.cs (limited to 'Software/Visual_Studio/Web/Tango.MachineService') diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index a4fcba41a..1924ce049 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 935b903b5..5096e2dc6 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/PMR/Messages/Diagnostics/DiagnosticsMonitors.proto b/Software/PMR/Messages/Diagnostics/DiagnosticsMonitors.proto index 28ebc5bc3..e367a00ce 100644 --- a/Software/PMR/Messages/Diagnostics/DiagnosticsMonitors.proto +++ b/Software/PMR/Messages/Diagnostics/DiagnosticsMonitors.proto @@ -202,7 +202,7 @@ message DiagnosticsMonitors repeated double HeadZone4HeaterCurrent = 61; //Head Zone 5-6 Heater Current (Min = 0, Max = 100, PPF = 1) - repeated double HeadZone5_6HeaterCurrent = 62; + repeated double HeadZone56HeaterCurrent = 62; //Mixer 1 Heater Current (Min = 0, Max = 100, PPF = 1) repeated double Mixer1HeaterCurrent = 63; diff --git a/Software/PMR/Messages/Insights/InsightsMonitors.proto b/Software/PMR/Messages/Insights/InsightsMonitors.proto index 627ad7255..d152e6181 100644 --- a/Software/PMR/Messages/Insights/InsightsMonitors.proto +++ b/Software/PMR/Messages/Insights/InsightsMonitors.proto @@ -200,7 +200,7 @@ message InsightsMonitors double HeadZone4HeaterCurrent = 61; //Head Zone 5-6 Heater Current - double HeadZone5_6HeaterCurrent = 62; + double HeadZone56HeaterCurrent = 62; //Mixer 1 Heater Current double Mixer1HeaterCurrent = 63; diff --git a/Software/PMR/Messages/Integration/ExternalBridgeUdpDiscoveryPacket.proto b/Software/PMR/Messages/Integration/ExternalBridgeUdpDiscoveryPacket.proto index d797e6de3..4a7d5b59b 100644 --- a/Software/PMR/Messages/Integration/ExternalBridgeUdpDiscoveryPacket.proto +++ b/Software/PMR/Messages/Integration/ExternalBridgeUdpDiscoveryPacket.proto @@ -7,4 +7,5 @@ message ExternalBridgeUdpDiscoveryPacket { string Time = 1; string SerialNumber = 2; + bool CompressionEnabled = 3; } \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Contracts/IInsightsView.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Contracts/IInsightsView.cs new file mode 100644 index 000000000..7ca881f9a --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Contracts/IInsightsView.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.FSE.Common; + +namespace Tango.FSE.Insights.Contracts +{ + public interface IInsightsView : IFSEView + { + void ZoomExtents(); + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsChart.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsChart.cs new file mode 100644 index 000000000..c51015e66 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsChart.cs @@ -0,0 +1,68 @@ +using SciChart.Charting.Model.ChartSeries; +using SciChart.Charting.Model.DataSeries; +using SciChart.Charting.Visuals.Annotations; +using SciChart.Charting.Visuals.RenderableSeries; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media; +using Tango.Core; + +namespace Tango.FSE.Insights.SciChart +{ + public class InsightsChart : ExtendedObject + { + public event EventHandler IsVisibleChanged; + + private ObservableCollection ChartsCollection { get; set; } + public String Name { get; set; } + public String Description { get; set; } + public PropertyInfo InsightsMonitorsProperty { get; set; } + public IRenderableSeriesViewModel RenderableSeries { get; set; } + public XyDataSeries DataSeries { get; set; } + public AnnotationCollection Annotations { get; set; } + + private bool _isVisible; + public bool IsVisible + { + get { return _isVisible; } + set + { + if (_isVisible != value) + { + _isVisible = value; + RaisePropertyChangedAuto(); + IsVisibleChanged?.Invoke(this, new EventArgs()); + } + } + } + + public bool IsLast + { + get + { + return ChartsCollection.Last() == this; + } + } + + public InsightsChart(ObservableCollection chartsCollection) + { + ChartsCollection = chartsCollection; + ChartsCollection.CollectionChanged += ChartsCollection_CollectionChanged; + RenderableSeries = new LineRenderableSeriesViewModel() { DrawNaNAs = LineDrawMode.Gaps }; + RenderableSeries.Stroke = Colors.DodgerBlue; + DataSeries = new XyDataSeries(); + RenderableSeries.DataSeries = DataSeries; + Annotations = new AnnotationCollection(); + } + + private void ChartsCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + RaisePropertyChanged(nameof(IsLast)); + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsRubberBandXYZoomModifier.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsRubberBandXYZoomModifier.cs new file mode 100644 index 000000000..21f7ecc8f --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsRubberBandXYZoomModifier.cs @@ -0,0 +1,24 @@ +using SciChart.Charting.ChartModifiers; +using SciChart.Core.Utility.Mouse; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace Tango.FSE.Insights.SciChart +{ + public class InsightsRubberBandXYZoomModifier : RubberBandXyZoomModifier + { + public override void OnModifierMouseDown(ModifierMouseArgs e) + { + //IsXAxisOnly = !e.IsMaster; + + if (Keyboard.Modifiers == ModifierKeys.Control) + { + base.OnModifierMouseDown(e); + } + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsZoomPanModifier.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsZoomPanModifier.cs new file mode 100644 index 000000000..00bb7beea --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsZoomPanModifier.cs @@ -0,0 +1,22 @@ +using SciChart.Charting.ChartModifiers; +using SciChart.Core.Utility.Mouse; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace Tango.FSE.Insights.SciChart +{ + public class InsightsZoomPanModifier : ZoomPanModifier + { + public override void OnModifierMouseDown(ModifierMouseArgs e) + { + if (!(Keyboard.Modifiers == ModifierKeys.Control)) + { + base.OnModifierMouseDown(e); + } + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Tango.FSE.Insights.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Tango.FSE.Insights.csproj index 83cb8cdef..623783f98 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Tango.FSE.Insights.csproj +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Tango.FSE.Insights.csproj @@ -58,6 +58,34 @@ ..\..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + + False + ..\..\..\Referenced Assemblies\SciChart\SciChart.Charting.dll + + + False + ..\..\..\Referenced Assemblies\SciChart\SciChart.Charting.DrawingTools.dll + + + False + ..\..\..\Referenced Assemblies\SciChart\SciChart.Charting3D.dll + + + False + ..\..\..\Referenced Assemblies\SciChart\SciChart.Core.dll + + + False + ..\..\..\Referenced Assemblies\SciChart\SciChart.Data.dll + + + False + ..\..\..\Referenced Assemblies\SciChart\SciChart.Drawing.dll + + + False + ..\..\..\Referenced Assemblies\SciChart\SciChart.Drawing.DirectX.dll + @@ -78,6 +106,10 @@ + + + + @@ -127,6 +159,10 @@ {a34ee0f0-649d-41c8-8489-b6f1cc6924ee} Tango.Core + + {4a55c185-3f8d-41b0-8815-c15f6213a14a} + Tango.Insights + {4206ac58-3b57-4699-8835-90bf6db01a61} Tango.Integration @@ -165,6 +201,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + Designer MSBuild:Compile diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Themes/Generic.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Themes/Generic.xaml new file mode 100644 index 000000000..4c8731fa1 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Themes/Generic.xaml @@ -0,0 +1,60 @@ + + + + + + + + + # + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ViewModels/InsightsViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ViewModels/InsightsViewVM.cs index 40b29c643..e5d09c282 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ViewModels/InsightsViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ViewModels/InsightsViewVM.cs @@ -1,13 +1,479 @@ -using System; +using SciChart.Charting.Model.ChartSeries; +using SciChart.Charting.Visuals.Annotations; +using SciChart.Charting.Visuals.RenderableSeries; +using SciChart.Data.Model; +using System; using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; using System.Linq; +using System.Reflection; using System.Text; +using System.Threading; using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Media; +using Tango.BL.Entities; +using Tango.BL.Enumerations; +using Tango.Core.Commands; using Tango.FSE.Common; +using Tango.FSE.Common.Insights; +using Tango.FSE.Insights.Contracts; +using Tango.FSE.Insights.SciChart; +using Tango.Logging; +using Tango.PMR.Insights; namespace Tango.FSE.Insights.ViewModels { - public class InsightsViewVM : FSEViewModel + public class InsightsViewVM : FSEViewModel { + private bool _chartsLoaded; + private ICollectionView _monitorsView; + + public RelayCommand GetInsightsCommand { get; set; } + + public ObservableCollection Charts { get; set; } + + public ObservableCollection VisibleCharts { get; set; } + + private DateTime _minDate; + public DateTime MinDate + { + get { return _minDate; } + set { _minDate = value; RaisePropertyChangedAuto(); } + } + + private DateTime _maxDate; + public DateTime MaxDate + { + get { return _maxDate; } + set { _maxDate = value; RaisePropertyChangedAuto(); } + } + + private DateTime? _startDate; + public DateTime? StartDate + { + get { return _startDate; } + set { _startDate = value; RaisePropertyChangedAuto(); } + } + + private DateTime? _startTime; + public DateTime? StartTime + { + get { return _startTime; } + set { _startTime = value; RaisePropertyChangedAuto(); } + } + + private DateTime? _endDate; + public DateTime? EndDate + { + get { return _endDate; } + set { _endDate = value; RaisePropertyChangedAuto(); } + } + + private DateTime? _endTime; + public DateTime? EndTime + { + get { return _endTime; } + set { _endTime = value; RaisePropertyChangedAuto(); } + } + + private InsightsHandler _handler; + public InsightsHandler Handler + { + get { return _handler; } + set { _handler = value; RaisePropertyChangedAuto(); } + } + + private IRange _visibleChartsRange; + public IRange VisibleChartsRange + { + get { return _visibleChartsRange; } + set { _visibleChartsRange = value; RaisePropertyChangedAuto(); } + } + + private String _monitorsFilter; + public String MonitorsFilter + { + get { return _monitorsFilter; } + set { _monitorsFilter = value; RaisePropertyChangedAuto(); OnMonitorsFilterChanged(); } + } + + private InsightsPackage _insightsPackage; + public InsightsPackage InsightsPackage + { + get { return _insightsPackage; } + set { _insightsPackage = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(InsightsPackageAvailable)); } + } + + public bool InsightsPackageAvailable + { + get { return InsightsPackage != null; } + } + + private bool _displayAnnotations; + public bool DisplayAnnotations + { + get { return _displayAnnotations; } + set { _displayAnnotations = value; RaisePropertyChangedAuto(); } + } + + private bool _isSearchBarOpened; + public bool IsSearchBarOpened + { + get { return _isSearchBarOpened; } + set { _isSearchBarOpened = value; RaisePropertyChangedAuto(); } + } + + public AnnotationCollection Annotations { get; set; } + + public InsightsViewVM() + { + IsSearchBarOpened = true; + Charts = new ObservableCollection(); + VisibleCharts = new ObservableCollection(); + Annotations = new AnnotationCollection(); + GetInsightsCommand = new RelayCommand(GetInsights, () => IsFree); + } + + public override void OnApplicationStarted() + { + base.OnApplicationStarted(); + StartDate = DateTime.Now.AddDays(-7); + StartTime = new DateTime(1, 1, 1, 0, 0, 0); + EndDate = null; + EndTime = null; + } + + public async override void OnApplicationReady() + { + base.OnApplicationReady(); + + if (!_chartsLoaded) + { + try + { + var monitors = (await Services.TechComponentsService.Monitors.FindAll()).OrderBy(x => x.Description).ToList(); + + foreach (var monitor in monitors.Where(x => !x.MultiChannel).ToList()) + { + InsightsChart chart = new InsightsChart(VisibleCharts); + chart.Name = monitor.Name; + chart.Description = monitor.Description; + chart.InsightsMonitorsProperty = typeof(InsightsMonitors).GetProperty(((TechMonitors)monitor.Code).ToString(), BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + chart.IsVisibleChanged += Chart_IsVisibleChanged; + chart.DataSeries.Append(GetDemoDates(), GetDemoValues()); + Charts.Add(chart); + } + + foreach (var chart in Charts.ToList().Where(x => x.InsightsMonitorsProperty == null)) + { + Charts.Remove(chart); + LogManager.Log($"Error loading insights chart '{chart.Name}'. Could not find property on InsightsMonitors.", LogCategory.Error); + } + + _monitorsView = CollectionViewSource.GetDefaultView(Charts); + _monitorsView.Filter = (x) => + { + if (!MonitorsFilter.IsNotNullOrEmpty()) return true; + + InsightsChart chart = x as InsightsChart; + if (chart != null) + { + return chart.Description.ToLower().Contains(MonitorsFilter.ToLower()); + } + + return false; + }; + + _chartsLoaded = true; + } + catch (Exception ex) + { + //TODO: Report Insights module error with BugReporting Snackbar... + } + } + } + + public override void OnNavigatedTo() + { + base.OnNavigatedTo(); + MinDate = DateTime.Now.AddDays(-30); + MaxDate = DateTime.Now; + } + + private async void GetInsights() + { + if (StartDate == null) + { + await NotificationProvider.ShowError("Please specify start date before trying to get insights."); + return; + } + + DateTime? start = null; + + if (StartTime != null) + { + start = + new DateTime( + StartDate.Value.Year, + StartDate.Value.Month, + StartDate.Value.Day, + StartTime.Value.Hour, + StartTime.Value.Minute, + StartTime.Value.Second); + } + else + { + start = StartDate.Value.Date; + } + + DateTime? end = null; + + if (EndDate != null) + { + if (EndTime != null) + { + end = + new DateTime( + EndDate.Value.Year, + EndDate.Value.Month, + EndDate.Value.Day, + EndTime.Value.Hour, + EndTime.Value.Minute, + EndTime.Value.Second); + } + else + { + end = EndDate.Value.Date.AddDays(1); + } + } + else + { + end = DateTime.Now.AddDays(1); + } + + LogManager.Log($"Getting insights from '{start.Value}' to '{end.Value}'"); + + try + { + IsSearchBarOpened = false; + + using (var task = NotificationProvider.PushTaskItem("Getting insights from the remote machine...", false, () => + { + try + { + Handler?.Abort(); + } + catch (Exception ex) + { + throw; + } + })) + { + IsFree = false; + Handler = await InsightsProvider.GetInsights(start.Value.ToUniversalTime(), end.Value.ToUniversalTime()); + Handler.ProgressChanged += (x, e) => + { + task.UpdateProgress(e.Progress.Message, e.Progress.Value, e.Progress.Maximum, e.Progress.IsIndeterminate); + }; + + task.CanCancel = true; + + var package = await Handler.WaitForCompletion(); + + task.CanCancel = false; + + await LoadInsightsPackage(package); + } + } + catch (ThreadAbortException) + { + IsSearchBarOpened = true; + //Operation canceled by cancel button.. + } + catch (OperationCanceledException) + { + IsSearchBarOpened = true; + //Aborted by user... + } + catch (Exception ex) + { + IsSearchBarOpened = true; + LogManager.Log(ex, "Error getting insights."); + await NotificationProvider.ShowError($"Error occurred while trying to get insights.\n{ex.FlattenMessage()}"); + } + finally + { + IsFree = true; + } + } + + private async Task LoadInsightsPackage(InsightsPackage package) + { + LogManager.Log($"Insights received with {package.Frames.Count} frames."); + + await Task.Factory.StartNew(() => + { + foreach (var chart in Charts) + { + chart.DataSeries.Clear(); + + List dates = new List(); + List values = new List(); + + foreach (var frame in package.Frames) + { + var value = chart.InsightsMonitorsProperty.GetValue(frame.Monitors); + + dates.Add(frame.Frame.Time.ToLocalTime()); + + if (value != null) + { + values.Add((double)value); + } + else + { + values.Add(double.NaN); + } + } + + chart.DataSeries.Append(dates, values); + } + + + InvokeUI(() => + { + Annotations.Clear(); + + //Load annotations + bool disconnected = false; + int positiveFrameCounter = 0; + + foreach (var frame in package.Frames) + { + if (frame.Frame.IsEmpty) + { + if (!disconnected && positiveFrameCounter > 1) + { + disconnected = true; + AddMachineConnectedDisconnectedAnnotation(frame.Frame.Time.ToLocalTime(), false); + } + + positiveFrameCounter = 0; + } + else + { + positiveFrameCounter++; + + if (disconnected) + { + disconnected = false; + AddMachineConnectedDisconnectedAnnotation(frame.Frame.Time.ToLocalTime(), true); + } + } + } + + PlotInsightsEvents(package); + InsightsPackage = package; + View.ZoomExtents(); + }); + }); + } + + public void AddMachineConnectedDisconnectedAnnotation(DateTime date, bool connected) + { + VerticalLineAnnotation line = new VerticalLineAnnotation(); + line.StrokeThickness = 2; + line.Stroke = connected ? Brushes.Green : Brushes.Red; + line.X1 = date; + line.X2 = date; + line.ShowLabel = false; + line.AnnotationLabels.Add(new AnnotationLabel() + { + LabelPlacement = LabelPlacement.TopRight, + Text = connected ? "machine connected" : "machine disconnected" + }); + Annotations.Add(line); + } + + private void PlotInsightsEvents(InsightsPackage package) + { + double y = 0.05; + + foreach (var ev in package.Events) + { + CustomAnnotation eventBox = new CustomAnnotation(); + eventBox.X1 = ev.Time.ToLocalTime(); + eventBox.Y1 = y; + eventBox.CoordinateMode = AnnotationCoordinateMode.RelativeY; + eventBox.Content = ev.EventType; + eventBox.ContentTemplate = Application.Current.Resources["InsightEventTemplate"] as DataTemplate; + Annotations.Add(eventBox); + + y += 0.05; + + if (y > 0.95) + { + y = 0.05; + } + } + } + + private void Chart_IsVisibleChanged(object sender, EventArgs e) + { + InsightsChart chart = sender as InsightsChart; + + if (chart.IsVisible) + { + VisibleCharts.Add(chart); + } + else + { + VisibleCharts.Remove(chart); + } + } + + private void OnMonitorsFilterChanged() + { + _monitorsView?.Refresh(); + } + + private List GetDemoDates() + { + List dates = new List(); + + for (int i = 0; i < 30; i++) + { + dates.Add(DateTime.Now.AddDays(-30).AddDays(i)); + } + + return dates; + } + + private List GetDemoValues() + { + List values = new List(); + + int counter2 = 0; + + for (int i = 0; i < 30; i++) + { + if (counter2 == 2) + { + values.Add(double.NaN); + counter2 = 0; + } + else + { + values.Add(i); + counter2++; + } + } + + return values; + } } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Views/InsightsView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Views/InsightsView.xaml index be3211e78..c70656c00 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Views/InsightsView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Views/InsightsView.xaml @@ -7,55 +7,234 @@ xmlns:vm="clr-namespace:Tango.FSE.Insights.ViewModels" xmlns:local="clr-namespace:Tango.FSE.Insights.Views" xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:insights="clr-namespace:Tango.FSE.Insights.SciChart" + xmlns:s="http://schemas.abtsoftware.co.uk/scichart" + xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common" mc:Ignorable="d" d:DesignHeight="1080" d:DesignWidth="1920" d:DataContext="{d:DesignInstance Type=vm:InsightsViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.InsightsViewVM}"> + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Views/InsightsView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Views/InsightsView.xaml.cs index 3d17caa97..e9107e100 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Views/InsightsView.xaml.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Views/InsightsView.xaml.cs @@ -1,4 +1,5 @@ -using System; +using SciChart.Charting.Visuals; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,17 +13,42 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; +using Tango.FSE.Insights.Contracts; namespace Tango.FSE.Insights.Views { /// /// Interaction logic for InsightsView.xaml /// - public partial class InsightsView : UserControl + public partial class InsightsView : UserControl, IInsightsView { public InsightsView() { InitializeComponent(); + this.Register(); + } + + private void SciChartSurface_Loaded(object sender, RoutedEventArgs e) + { + Grid grid = sender as Grid; + + if (grid != null) + { + SciChartSurface chart = grid.FindChild(); + + if (chart != null) + { + chart.ZoomExtents(); + } + } + } + + public void ZoomExtents() + { + foreach (var chart in chartsItemsControl.FindVisualChildren()) + { + chart.ZoomExtents(); + } } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/EntityFrameworkExtensionsHelper.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/EntityFrameworkExtensionsHelper.cs new file mode 100644 index 000000000..0f5ce3cf1 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/EntityFrameworkExtensionsHelper.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.BL +{ + public static class EntityFrameworkExtensionsHelper + { + public static void SetupLicense(String licenseName, String licenseKey) + { + Z.EntityFramework.Extensions.LicenseManager.AddLicense(licenseName, licenseKey); + + string licenseErrorMessage; + if (!Z.EntityFramework.Extensions.LicenseManager.ValidateLicense(out licenseErrorMessage)) + { + throw new Exception(licenseErrorMessage); + } + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj b/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj index b1b0b300e..b28f8b45a 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj @@ -83,6 +83,7 @@ + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs index 07d2a7a5b..efe9e877a 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs @@ -44,6 +44,7 @@ using Tango.FSE.Common.RemoteJob; using Tango.FSE.Common.WindowsManager; using Tango.FSE.Common.DemoMode; using Tango.FSE.Common.FileAssociation; +using Tango.FSE.Common.Insights; namespace Tango.FSE.Common { @@ -235,6 +236,12 @@ namespace Tango.FSE.Common [TangoInject] public IFileAssociationProvider FileAssociationProvider { get; set; } + /// + /// Gets or sets the insights provider. + /// + [TangoInject] + public IInsightsProvider InsightsProvider { get; set; } + /// /// Gets or sets the FSE service. /// diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FileSystem/IFileSystemProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileSystem/IFileSystemProvider.cs index a97a44f81..32c795ffc 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FileSystem/IFileSystemProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileSystem/IFileSystemProvider.cs @@ -49,9 +49,19 @@ namespace Tango.FSE.Common.FileSystem /// /// The file or folder. /// The local target folder or file. - /// Indicates whether the localTargetFolder is a file. + /// Indicates whether the localTargetFolder is a file. /// - Task Download(FileSystemItem item, String localTargetFolderOrFile, bool isSingleFile = false); + Task Download(FileSystemItem item, String localTargetFolderOrFile, bool isLocaTargetFile = false); + + /// + /// Downloads the specified file or folder item. + /// + /// The remote file or folder. + /// Indicates whether the remote path is a file. + /// The local target folder or file. + /// Indicates whether the localTargetFolder is a file. + /// + Task Download(String remotePath, bool isRemotePathFile, String localTargetFolderOrFile, bool isLocalTargetFile = false); /// /// Uploads the specified local file or folder. diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/IInsightsProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/IInsightsProvider.cs new file mode 100644 index 000000000..f90e398fd --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/IInsightsProvider.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Common.Insights +{ + public interface IInsightsProvider + { + Task GetInsights(DateTime startDateUTC, DateTime endTimeUTC); + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsHandler.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsHandler.cs new file mode 100644 index 000000000..a263a50bb --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsHandler.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; + +namespace Tango.FSE.Common.Insights +{ + public class InsightsHandler : ExtendedObject + { + private Action _abortAction; + private TaskCompletionSource _completionSource; + private bool _completed; + + public event EventHandler StatusChanged; + public event EventHandler> ProgressChanged; + public event EventHandler Completed; + + + private InsightsHandlerStatus _status; + public InsightsHandlerStatus Status + { + get { return _status; } + set + { + if (_status != value) + { + _status = value; + RaisePropertyChangedAuto(); + StatusChanged?.Invoke(this, _status); + } + } + } + + private TangoProgress _progress; + public TangoProgress Progress + { + get { return _progress; } + set + { + _progress = value; RaisePropertyChangedAuto(); + + if (_progress != null) + { + ProgressChanged?.Invoke(this, new TangoProgressChangedEventArgs(_progress)); + } + } + } + + private Exception _failedException; + public Exception FailedException + { + get { return _failedException; } + set { _failedException = value; RaisePropertyChangedAuto(); } + } + + public InsightsHandler(Action abortAction) + { + _completionSource = new TaskCompletionSource(); + _abortAction = abortAction; + Progress = new TangoProgress("Initializing..."); + } + + public void Abort() + { + if (!_completed) + { + _completed = true; + _abortAction?.Invoke(); + Status = InsightsHandlerStatus.Aborted; + _completionSource.SetException(new OperationCanceledException()); + } + } + + public void RaiseFailed(Exception ex) + { + if (!_completed) + { + _completed = true; + FailedException = ex; + Status = InsightsHandlerStatus.Failed; + _completionSource.SetException(ex); + } + } + + public void RaiseCompleted(InsightsPackage package) + { + if (!_completed) + { + _completed = true; + Status = InsightsHandlerStatus.Completed; + Completed?.Invoke(this, package); + _completionSource.SetResult(package); + } + } + + public Task WaitForCompletion() + { + return _completionSource.Task; + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsHandlerStatus.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsHandlerStatus.cs new file mode 100644 index 000000000..ec911b836 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsHandlerStatus.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Common.Insights +{ + public enum InsightsHandlerStatus + { + Initializing, + Downloading, + Composing, + Completed, + Failed, + Aborted, + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsPackage.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsPackage.cs new file mode 100644 index 000000000..96718f6bf --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsPackage.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; +using Tango.Insights; + +namespace Tango.FSE.Common.Insights +{ + public class InsightsPackage + { + public List Frames { get; set; } + public List Events { get; set; } + + public InsightsPackage() + { + Frames = new List(); + Events = new List(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsReadyEvent.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsReadyEvent.cs new file mode 100644 index 000000000..0378e6a5a --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsReadyEvent.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; + +namespace Tango.FSE.Common.Insights +{ + public class InsightsReadyEvent + { + public DateTime Time { get; set; } + public EventType EventType { get; set; } + + public override string ToString() + { + return $"{Time}: {EventType.Name}"; + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsReadyFrame.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsReadyFrame.cs new file mode 100644 index 000000000..b4ad8ec50 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsReadyFrame.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Insights; +using Tango.PMR.Insights; + +namespace Tango.FSE.Common.Insights +{ + public class InsightsReadyFrame + { + public InsightsFrame Frame { get; private set; } + public InsightsMonitors Monitors { get; private set; } + + public InsightsReadyFrame(InsightsFrame frame) + { + Frame = frame; + Monitors = frame.ToInsightsMonitors(); + } + + public override string ToString() + { + return $"{Frame.Time}: {Monitors.ToString()}"; + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/INotificationProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/INotificationProvider.cs index 5fff158fd..1a5026e8e 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/INotificationProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/INotificationProvider.cs @@ -257,8 +257,10 @@ namespace Tango.FSE.Common.Notifications /// Pushes the task item with the specified message. /// /// The message. + /// Indicates whether the cancel button will be enabled. + /// Specify the action to execute when cancel button is pressed. /// - TaskItem PushTaskItem(String message); + TaskItem PushTaskItem(String message, bool canCancel = false, Action cancelAction = null); /// /// Pops the task item. diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/TaskItem.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/TaskItem.cs index 048374727..9492433f6 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/TaskItem.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/TaskItem.cs @@ -22,10 +22,10 @@ namespace Tango.FSE.Common.Notifications } private bool _hasCancel; - public bool HasCancel + public bool CanCancel { get { return _hasCancel; } - set { _hasCancel = value; RaisePropertyChangedAuto(); } + set { _hasCancel = value; RaisePropertyChangedAuto(); CancelCommand?.RaiseCanExecuteChanged(); } } public RelayCommand CancelCommand { get; set; } @@ -43,7 +43,12 @@ namespace Tango.FSE.Common.Notifications public TaskItem(String message, Action cancelAction) : this(message) { _cancelAction = cancelAction; - HasCancel = true; + CancelCommand = new RelayCommand(() => + { + CanCancel = false; + cancelAction?.Invoke(); + }, () => CanCancel); + CanCancel = true; } public void UpdateProgress(String message, double value = 0, double maximum = 100, bool isIndeterminate = true) diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml index dce8bea15..922790d5e 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml @@ -44,4 +44,5 @@ + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj index 0584d2e0b..d2208615b 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj @@ -85,6 +85,34 @@ ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Charting.dll + + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Charting.DrawingTools.dll + + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Charting3D.dll + + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Core.dll + + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Data.dll + + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Drawing.dll + + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Drawing.DirectX.dll + @@ -198,6 +226,12 @@ + + + + + + @@ -470,6 +504,10 @@ {c6ebbbbe-2123-44dc-aef7-a0d47d736ac0} Tango.FileSystem + + {4A55C185-3F8D-41B0-8815-C15F6213A14A} + Tango.Insights + {4206ac58-3b57-4699-8835-90bf6db01a61} Tango.Integration @@ -569,6 +607,7 @@ + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml index 73680103b..fc6f427c1 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml @@ -3,6 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz" + xmlns:s="http://schemas.abtsoftware.co.uk/scichart" xmlns:local="clr-namespace:Tango.FSE.UI" StartupUri="MainWindow.xaml"> @@ -92,12 +93,24 @@ + + + + + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs index de0594703..047df9f50 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using SciChart.Charting.Visuals; using System; using System.Collections.Generic; using System.Configuration; @@ -13,6 +14,7 @@ using System.Windows; using System.Windows.Markup; using Tango.Core.DI; using Tango.Core.Helpers; +using Tango.FSE.BL; using Tango.FSE.Common; using Tango.FSE.Common.BugReporting; using Tango.FSE.Common.FileAssociation; @@ -131,6 +133,24 @@ namespace Tango.FSE.UI WebRequest.DefaultWebProxy = null; + try + { + EntityFrameworkExtensionsHelper.SetupLicense("4578;101-twine-s.com", "9d23b66f-1101-b253-7f8a-59ae011b2ee8"); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error performing EF extensions license setup."); + } + + try + { + SciChartSurface.SetRuntimeLicenseKey("27FuI+bWcfmLHSBlM4B8nUs23aeeXvft2+7Pxj0fOrcnruWXyOm/swjI2PpoBPOKS9dNVtw60E4Xdpq4Ts8UgMWQHU8qcJtPoAyNQqbVMQNOr/sv1QpSD2mRjogERcrGty+tvlCHMGhkw/TOiL5DPnw5rOPqGfymyRuJRNFTTYB/hCIAiCt7VIlyHhO+uo0DOfxIC+gNVKoWyGd0xdQ3xSUmfdNvUigW7ZkUKDkAIBpRcmOLx5wV4y77I/4MghTl3FAZlhhFoBdAUKLZWpbISU8xfAUkI1s/md0mAztMTbqzkRT94AsSI1/KPnH7fuuH82ABJcp0UnKWh8aIlkbjD2vVCKXn9omMBEBRmTx68IuHoP4iT5mTyd6R3OfnEM6Vc6AZ9SLytjoP7Iu2hPKR7uqGJW/2KZ0jIZ4Hn+bJfl23fBexgJl4jK33aeIIkw/Og67w/CRK4MgiHtSLp7x1I3Fsmw8EYbQ2nZe3lA4SH1DU"); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error settings SciChart runtime license."); + } + base.OnStartup(e); exceptionTrapper = new WpfGlobalExceptionTrapper(); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs index 6e1ec93a6..55866361b 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs @@ -162,7 +162,7 @@ namespace Tango.FSE.UI.Connection { _machineEventsStateProvider = new FSEMachineEventsStateProvider(); - MachineOperator = new ExternalBridgeTcpClient("N/A", "N/A"); + MachineOperator = new ExternalBridgeTcpClient("N/A", "N/A", false); MachineOperator.MachineEventsStateProvider = _machineEventsStateProvider; MachineOperator.StateChanged += MachineOperator_StateChanged; MachineOperator.As().SessionClosed += DefaultMachineProvider_SessionClosed; @@ -185,7 +185,7 @@ namespace Tango.FSE.UI.Connection { try { - LogManager.Log($"Connecting to machine '{machine.GetType().Name}' => '{machine.SerialNumber}' => '{machine.Adapter?.Address}'..."); + LogManager.Log($"Connecting to machine '{machine.GetType().Name}' => '{machine.SerialNumber}' => '{machine.Adapter?.Address}' => {(machine.CompressionEnabled ? "Compression Enabled" : "Compression Disabled")}..."); IsBusy = true; diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Controls/NotificationsControl.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Controls/NotificationsControl.xaml index a0715a96f..4e6ada6b5 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Controls/NotificationsControl.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Controls/NotificationsControl.xaml @@ -267,7 +267,7 @@ - + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs index 6673a5ae3..e7f9772ff 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs @@ -167,7 +167,10 @@ namespace Tango.FSE.UI.FileSystem Priority = QueuePriority.Low }); - _webRtcTransporter = new BasicTransporter(new WebRtcTransportAdapter(_machineProvider.MachineOperator, WebRtcTransportAdapterMode.Active, WEB_RTC_CHANNEL_NAME)); + _webRtcTransporter = new BasicTransporter(new WebRtcTransportAdapter(_machineProvider.MachineOperator, WebRtcTransportAdapterMode.Active, WEB_RTC_CHANNEL_NAME) + { + EnableCompression = _machineProvider.MachineOperator.CompressionEnabled, + }); _webRtcTransporter.UseKeepAlive = false; _webRtcTransporter.ComponentName = "File System Active WebRTC Transporter"; await _webRtcTransporter.Connect(); @@ -272,11 +275,12 @@ namespace Tango.FSE.UI.FileSystem /// /// Downloads the specified file or folder item. /// - /// The file or folder. + /// The remote file or folder. + /// Indicates whether the remote path is a file. /// The local target folder or file. - /// Indicates whether the localTargetFolder is a file. + /// Indicates whether the localTargetFolder is a file. /// - public Task Download(FileSystemItem item, String localTargetFolderOrFile, bool isSingleFile = false) + public Task Download(FileSystemItem item, String localTargetFolderOrFile, bool isLocalTargetFile = false) { AuthenticationProvider.ThrowIfNoPermission(Permissions.FSE_PPCFileSystemRead); @@ -289,7 +293,7 @@ namespace Tango.FSE.UI.FileSystem FileSystemHandler handler = null; - if (isSingleFile) + if (isLocalTargetFile) { destination = localTargetFolderOrFile; } @@ -536,6 +540,32 @@ namespace Tango.FSE.UI.FileSystem return Task.FromResult(handler); } + /// + /// Downloads the specified file or folder item. + /// + /// The remote file or folder. + /// Indicates whether the remote path is a file. + /// The local target folder or file. + /// Indicates whether the localTargetFolder is a file. + /// + public Task Download(String remotePath, bool isRemotePathFile, String localTargetFolderOrFile, bool isLocalTargetFile = false) + { + FileSystemItem item = null; + + if (isRemotePathFile) + { + item = new FileItem(); + } + else + { + item = new FolderItem(); + } + + item.Path = remotePath; + + return Download(item, localTargetFolderOrFile, isLocalTargetFile); + } + /// /// Uploads the specified local file or folder. /// diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs new file mode 100644 index 000000000..1e9996bd2 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; +using Tango.Core; +using Tango.Core.DI; +using Tango.FSE.BL; +using Tango.FSE.Common.Connection; +using Tango.FSE.Common.FileSystem; +using Tango.FSE.Common.Insights; +using Tango.Insights; +using Tango.PPC.Shared.Insights; + +namespace Tango.FSE.UI.Insights +{ + public class DefaultInsightsProvider : ExtendedObject, IInsightsProvider + { + [TangoInject] + private IMachineProvider MachineProvider { get; set; } + + [TangoInject] + private IFileSystemProvider FileSystemProvider { get; set; } + + [TangoInject] + private FSEServicesContainer Services { get; set; } + + public async Task GetInsights(DateTime startDateUTC, DateTime endTimeUTC) + { + InsightsHandler handler = null; + + var response = await MachineProvider.MachineOperator.SendGenericRequest(new InsightsRequest() + { + StartDateUTC = startDateUTC, + EndDateUTC = endTimeUTC + }, new Transport.TransportRequestConfig() + { + Timeout = TimeSpan.FromMinutes(1), + }); + + var insightsFilePath = TemporaryManager.CreateImaginaryFile(".insights"); + var fileSystemHandler = await FileSystemProvider.Download(response.InisightsFilePath, true, insightsFilePath, true); + + handler = new InsightsHandler(() => + { + fileSystemHandler.Abort(); + }); + + fileSystemHandler.StatusChanged += (x, status) => + { + if (status == FileSystemHandlerStatus.Downloading) + { + handler.Status = InsightsHandlerStatus.Downloading; + } + else if (status == FileSystemHandlerStatus.Completed) + { + Task.Factory.StartNew(() => + { + try + { + handler.Progress = new TangoProgress("Composing insights..."); + + handler.Status = InsightsHandlerStatus.Composing; + + var package = new InsightsPackage(); + + var insightsFile = InsightsFile.FromFile(insightsFilePath); + + int progress = 0; + + foreach (var frame in insightsFile.Frames.OrderBy(xx => xx.Time)) + { + if (handler.Status == InsightsHandlerStatus.Aborted) + { + return; + } + + package.Frames.Add(new InsightsReadyFrame(frame)); + progress++; + handler.Progress = new TangoProgress("Composing insights...", false, progress, insightsFile.Frames.Count); + } + + handler.Progress = new TangoProgress("Composing insights..."); + + progress = 0; + + var eventTypes = Services.MachineEventsService.GetAllEventTypes().Result; + Dictionary eventsDictionary = new Dictionary(); + foreach (var eventType in eventTypes) + { + eventsDictionary.Add(eventType.Code, eventType); + } + + foreach (var ev in insightsFile.Events.OrderBy(xx => xx.Time)) + { + if (handler.Status == InsightsHandlerStatus.Aborted) + { + return; + } + + EventType eventType = eventsDictionary[ev.EventCode]; + package.Events.Add(new InsightsReadyEvent() + { + Time = ev.Time, + EventType = eventType, + }); + + progress++; + handler.Progress = new TangoProgress("Composing insights...", false, progress, insightsFile.Events.Count); + } + + handler.RaiseCompleted(package); + } + catch (Exception ex) + { + handler.RaiseFailed(ex); + } + }); + } + else if (status == FileSystemHandlerStatus.Failed) + { + handler.RaiseFailed(fileSystemHandler.FailedException); + } + }; + + fileSystemHandler.ProgressChanged += (x, e) => + { + e.Progress.Message = "Getting insights from the remote machine..."; + handler.Progress = e.Progress; + }; + + return handler; + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Notifications/DefaultNotificationProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Notifications/DefaultNotificationProvider.cs index 368752120..0ebf457eb 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Notifications/DefaultNotificationProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Notifications/DefaultNotificationProvider.cs @@ -667,13 +667,22 @@ namespace Tango.FSE.UI.Notifications } /// - /// Pushes the task item. + /// Pushes the task item with the specified message. /// - /// + /// The message. + /// Indicates whether the cancel button will be enabled. + /// Specify the action to execute when cancel button is pressed. /// - public TaskItem PushTaskItem(String message) + public TaskItem PushTaskItem(String message, bool canCancel = false, Action cancelAction = null) { - return PushTaskItem(new TaskItem(message)); + if (canCancel || cancelAction != null) + { + return PushTaskItem(new TaskItem(message, cancelAction)); + } + else + { + return PushTaskItem(new TaskItem(message)); + } } /// diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/ConnectedMachinePane.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/ConnectedMachinePane.xaml index e5791f23c..db2559a9d 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/ConnectedMachinePane.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/ConnectedMachinePane.xaml @@ -79,6 +79,8 @@ + + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj index ee1b0bd29..24cbfd55f 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj @@ -98,6 +98,34 @@ ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Charting.dll + + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Charting.DrawingTools.dll + + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Charting3D.dll + + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Core.dll + + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Data.dll + + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Drawing.dll + + + False + ..\..\Referenced Assemblies\SciChart\SciChart.Drawing.DirectX.dll + ..\..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll @@ -277,6 +305,7 @@ + @@ -613,6 +642,10 @@ {c6ebbbbe-2123-44dc-aef7-a0d47d736ac0} Tango.FileSystem + + {4A55C185-3F8D-41B0-8815-C15F6213A14A} + Tango.Insights + {4206AC58-3B57-4699-8835-90BF6DB01A61} Tango.Integration diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs index 25d0b45c9..5da32809f 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs @@ -66,6 +66,8 @@ using Tango.FSE.Common.SQL; using Tango.FSE.UI.SQL; using Tango.FSE.Common.FileAssociation; using Tango.FSE.UI.FileAssociation; +using Tango.FSE.Common.Insights; +using Tango.FSE.UI.Insights; namespace Tango.FSE.UI { @@ -104,6 +106,7 @@ namespace Tango.FSE.UI TangoIOC.Default.Unregister(); TangoIOC.Default.Unregister(); TangoIOC.Default.Unregister(); + TangoIOC.Default.Unregister(); //TangoIOC.Default.Unregister(); //TangoIOC.Default.Unregister(); //TangoIOC.Default.Unregister(); @@ -142,6 +145,7 @@ namespace Tango.FSE.UI TangoIOC.Default.Register(); TangoIOC.Default.Register(); TangoIOC.Default.Register(); + TangoIOC.Default.Register(); TangoIOC.Default.Register(); diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml index 4f7385513..d436c58b7 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml @@ -296,12 +296,17 @@ + + External Bridge Transport Compression + + + Enable External Bridge SignalR - + External Bridge SignalR Hub @@ -328,6 +333,26 @@ + + Enable Insights + + + + + Insights Sampling Interval (sec) + + + + + Insights Storage Cleanup Interval (min) + + + + + Insights Max Storage Duration (days) + + + diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/ExternalBridge/PPCExternalBridgeService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/ExternalBridge/PPCExternalBridgeService.cs index 6eaeb58a0..236c066e3 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/ExternalBridge/PPCExternalBridgeService.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/ExternalBridge/PPCExternalBridgeService.cs @@ -53,6 +53,7 @@ namespace Tango.PPC.Common.ExternalBridge applicationManager.ApplicationReady += (_, __) => { var settings = SettingsManager.Default.GetOrCreate(); + EnableTransportCompression = settings.EnableExternalBridgeTransportCompression; MachineOperator = machineProvider.MachineOperator; Machine = machineProvider.Machine; SignalRConfiguration.Enabled = settings.EnableExternalBridgeSignalR; diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/FileSystem/DefaultFileSystemService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/FileSystem/DefaultFileSystemService.cs index 86506abcf..958c1aa12 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/FileSystem/DefaultFileSystemService.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/FileSystem/DefaultFileSystemService.cs @@ -15,6 +15,7 @@ using Tango.Integration.Operation; using Tango.Logging; using Tango.PPC.Common.ExternalBridge; using Tango.PPC.Shared.Logs; +using Tango.Settings; using Tango.Transport; using Tango.Transport.Transporters; using Tango.WebRTC; @@ -33,6 +34,7 @@ namespace Tango.PPC.Common.FileSystem private FileSystemManager _manager; private Dictionary _operations; private Dictionary _webRtcClients; + private bool _enableCompression; public bool Enabled { get; set; } = true; public bool EnableWebRTC { get; set; } = true; @@ -43,6 +45,7 @@ namespace Tango.PPC.Common.FileSystem _manager = new FileSystemManager(); _operations = new Dictionary(); externalBridge.RegisterRequestHandler(this); + _enableCompression = SettingsManager.Default.GetOrCreate().EnableExternalBridgeTransportCompression; } [ExternalBridgeRequestHandlerMethod(typeof(InitWebRtcRequest), RequestHandlerLoggingMode.LogRequestNameAndContent)] @@ -66,7 +69,10 @@ namespace Tango.PPC.Common.FileSystem } LogManager.Log("Initializing WebRTC transport adapter on 'Passive' mode."); - var webRtcAdapter = new WebRtcTransportAdapter(receiver, WebRtcTransportAdapterMode.Passive, request.DataChannelName); + var webRtcAdapter = new WebRtcTransportAdapter(receiver, WebRtcTransportAdapterMode.Passive, request.DataChannelName) + { + EnableCompression = _enableCompression + }; webRtcAdapter.Ready += (x, e) => { LogManager.Log("The file system service WebRTC channel is ready."); diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs index bfbf7114f..24852d853 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using Tango.BL; using Tango.Core; using Tango.Core.DI; using Tango.Insights; @@ -74,6 +75,8 @@ namespace Tango.PPC.Common.Insights { var frames = InsightsManager.Default.GetFrames(request.StartDateUTC, request.EndDateUTC); insightsFile.Frames = frames; + insightsFile.Events = InsightsManager.Default.GetEvents(request.StartDateUTC, request.EndDateUTC); + insightsFile.ToFile(filePath); }); diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs index 9afbb52b6..bd21b3bb0 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs @@ -60,6 +60,11 @@ namespace Tango.PPC.Common /// public String ExternalBridgePassword { get; set; } + /// + /// Gets or sets a value indicating whether to enable transport compression for external bridge clients. + /// + public bool EnableExternalBridgeTransportCompression { get; set; } + /// /// Gets or sets a value indicating whether [enable hot spot]. /// @@ -296,6 +301,7 @@ namespace Tango.PPC.Common EmbeddedComPort = "COM10"; EmbeddedDeviceHint = "Tango USB Serial Port"; ExternalBridgePassword = "Aa123456"; + EnableExternalBridgeTransportCompression = true; HotSpotPassword = "Aa123456"; LockScreenTimeout = TimeSpan.FromMinutes(10); LockScreenPassword = "1111"; diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Resources/Merged.xaml b/Software/Visual_Studio/PPC/Tango.PPC.Common/Resources/Merged.xaml index 955a584c2..806a94bb0 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Resources/Merged.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Resources/Merged.xaml @@ -54,6 +54,7 @@ +