From 9259bc36791a7084ae33bcf0a698101ddb24d28f Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Thu, 5 Dec 2019 18:06:21 +0200 Subject: Integrated CDN downloads to PPC and MS. --- .../MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs index 2ee8574b1..160041b5f 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/UpdateViewVM.cs @@ -179,6 +179,7 @@ namespace Tango.MachineStudio.UI.ViewModels _updateInfo = new CheckForUpdatesResponse(); _updateInfo.BlobAddress = response.BlobAddress; _updateInfo.Version = response.Version; + _updateInfo.CdnAddress = response.CdnAddress; LatestVersion = _updateInfo.Version; StartUpdate(); @@ -270,7 +271,7 @@ namespace Tango.MachineStudio.UI.ViewModels { logManager.Log("Creating temporary file " + tempFile); - using (StorageBlobDownloader downloader = new StorageBlobDownloader(_updateInfo.BlobAddress, tempFile.Path)) + using (AutoFileDownloader downloader = new AutoFileDownloader(_updateInfo.BlobAddress, _updateInfo.CdnAddress, tempFile.Path)) { downloader.Progress += (x, e) => { -- cgit v1.3.1 From d1859415972bb991cba6639482c1cd2a9e19e8d8 Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Sun, 8 Dec 2019 15:28:31 +0200 Subject: Implemented possible improvement for WebClient download speed. Implemented PPC notifications priority. --- .../ViewModels/MachineUpdatesViewVM.cs | 11 +++++------ .../MachineStudio/Tango.MachineStudio.UI/App.xaml.cs | 3 +++ .../Tango.PPC.Events/ViewModels/MainViewVM.cs | 4 ++++ .../Modules/Tango.PPC.Jobs/ViewModels/MainViewVM.cs | 2 +- .../Notifications/INotificationProvider.cs | 6 ++++++ .../Notifications/NotificationItem.cs | 15 +++++++++++++++ .../NotificationItems/MessageNotificationItem.cs | 2 +- Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs | 3 +++ .../Notifications/DefaultNotificationProvider.cs | 10 ++++++++++ .../UpdateAvailableNotificationItemView.xaml | 2 +- .../Tango.Touch/Controls/TouchNotificationBar.cs | 20 +++++++++++++++++--- .../Tango.Transport/Web/StandardFileDownloader.cs | 1 + 12 files changed, 67 insertions(+), 12 deletions(-) (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MachineUpdatesViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MachineUpdatesViewVM.cs index 7ff64c505..c3c3baa70 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MachineUpdatesViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MachineUpdatesViewVM.cs @@ -129,12 +129,11 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels private void OnSelectedUpdateChanged() { - if (SelectedUpdate == null) return; - - var selectedUpdate = SelectedUpdate; - SelectedUpdate = null; - - _notification.ShowModalDialog(new MachineUpdateDetailsDialogVM() { Update = selectedUpdate }, (vm) => { }, () => { }); + if (SelectedUpdate != null && SelectedUpdate.ApplicationVersion != "Fake") + { + _notification.ShowModalDialog(new MachineUpdateDetailsDialogVM() { Update = SelectedUpdate }, (vm) => { }, () => { }); + SelectedUpdate = new TangoUpdate() { ApplicationVersion = "Fake"}; + } } #endregion diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs index 94f98feb2..345503ed3 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs @@ -24,6 +24,7 @@ using Tango.MachineStudio.Common; using Tango.Core; using Tango.BL; using Tango.Integration.Operation; +using System.Net; namespace Tango.MachineStudio.UI { @@ -98,6 +99,8 @@ namespace Tango.MachineStudio.UI exceptionTrapper.ApplicationCrashed += ExceptionTrapper_ApplicationCrashed; ApplyEFCacheSettings(); + + WebRequest.DefaultWebProxy = null; } private void ApplyEFCacheSettings() diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Events/ViewModels/MainViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Events/ViewModels/MainViewVM.cs index d2a730cd7..3f549598a 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Events/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Events/ViewModels/MainViewVM.cs @@ -144,15 +144,19 @@ namespace Tango.PPC.Events.ViewModels { case EventTypeCategories.Info: notificationItem.MessageType = MessageNotificationItem.MessageNotificationItemTypes.Info; + notificationItem.Priority = NotificationItem.NotificationPriority.Normal; break; case EventTypeCategories.Warning: notificationItem.MessageType = MessageNotificationItem.MessageNotificationItemTypes.Warning; + notificationItem.Priority = NotificationItem.NotificationPriority.High; break; case EventTypeCategories.Error: notificationItem.MessageType = MessageNotificationItem.MessageNotificationItemTypes.Error; + notificationItem.Priority = NotificationItem.NotificationPriority.VeryHigh; break; case EventTypeCategories.Critical: notificationItem.MessageType = MessageNotificationItem.MessageNotificationItemTypes.Critical; + notificationItem.Priority = NotificationItem.NotificationPriority.Critical; break; } diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/MainViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/MainViewVM.cs index ed1e28f55..624b192a5 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/MainViewVM.cs @@ -85,7 +85,7 @@ namespace Tango.PPC.Jobs.ViewModels { NavigationManager.NavigateWithObject(e.Job); NavigationManager.ClearHistoryExcept(); - })); + }, NotificationItem.NotificationPriority.Critical)); } /// diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/INotificationProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/INotificationProvider.cs index c4e82b7d2..4a0627d70 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/INotificationProvider.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/INotificationProvider.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -22,6 +23,11 @@ namespace Tango.PPC.Common.Notifications /// ObservableCollection NotificationItems { get; } + /// + /// Gets the notification items view. + /// + ICollectionView NotificationItemsView { get; } + /// /// Gets the collection of taskbar items. /// diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/NotificationItem.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/NotificationItem.cs index c96fe9dee..cf81237ca 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/NotificationItem.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/NotificationItem.cs @@ -14,12 +14,22 @@ namespace Tango.PPC.Common.Notifications /// public abstract class NotificationItem : ItemBase { + public enum NotificationPriority + { + Low, + Normal, + High, + VeryHigh, + Critical, + } + /// /// Initializes a new instance of the class. /// public NotificationItem() : base() { CanClose = true; + Priority = NotificationPriority.Normal; } private bool _isExpanded; @@ -42,6 +52,11 @@ namespace Tango.PPC.Common.Notifications set { _canClose = value; RaisePropertyChangedAuto(); } } + /// + /// Gets or sets the notification priority. + /// + public NotificationPriority Priority { get; set; } + /// /// Called when the item has been pressed. /// diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/NotificationItems/MessageNotificationItem.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/NotificationItems/MessageNotificationItem.cs index a9de336a1..571eb199d 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/NotificationItems/MessageNotificationItem.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/NotificationItems/MessageNotificationItem.cs @@ -77,7 +77,7 @@ namespace Tango.PPC.Common.Notifications.NotificationItems /// The expanded message. /// The type. /// The pressed action. - public MessageNotificationItem(String message, String expandedMessage, MessageNotificationItemTypes type, Action pressedAction) : this() + public MessageNotificationItem(String message, String expandedMessage, MessageNotificationItemTypes type, Action pressedAction, NotificationPriority priority = NotificationPriority.Normal) : this() { Message = message; ExpandedMessage = expandedMessage; diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs index bd3f04958..f9261e754 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs @@ -5,6 +5,7 @@ using System.Data; using System.Diagnostics; using System.IO; using System.Linq; +using System.Net; using System.Threading.Tasks; using System.Windows; using Tango.BL; @@ -89,6 +90,8 @@ namespace Tango.PPC.UI settings.Save(); LogManager.Categories.AddRange(settings.LoggingCategories); + + WebRequest.DefaultWebProxy = null; } #region Global Exception Trapping diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Notifications/DefaultNotificationProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Notifications/DefaultNotificationProvider.cs index 65337a892..a8ac2b24b 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Notifications/DefaultNotificationProvider.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Notifications/DefaultNotificationProvider.cs @@ -17,6 +17,8 @@ using Tango.Touch.Controls; using Tango.SharedUI; using System.Reflection; using Tango.Core.DI; +using System.ComponentModel; +using System.Windows.Data; namespace Tango.PPC.UI.Notifications { @@ -46,6 +48,11 @@ namespace Tango.PPC.UI.Notifications /// public ObservableCollection NotificationItems { get; private set; } + /// + /// Gets the notification items view. + /// + public ICollectionView NotificationItemsView { get; private set; } + /// /// Gets the collection of taskbar items. /// @@ -66,6 +73,9 @@ namespace Tango.PPC.UI.Notifications PopNotificationCommand = new RelayCommand((x) => PopNotification(x)); NotificationItems.EnableCrossThreadOperations(); + + NotificationItemsView = CollectionViewSource.GetDefaultView(NotificationItems); + NotificationItemsView.SortDescriptions.Add(new SortDescription(nameof(NotificationItem.Priority), ListSortDirection.Descending)); } private MessageBoxVM _currentMessageBox; diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Notifications/NotificationItems/UpdateAvailableNotificationItemView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Notifications/NotificationItems/UpdateAvailableNotificationItemView.xaml index fc9b05b9b..1d4dd6fc7 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Notifications/NotificationItems/UpdateAvailableNotificationItemView.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Notifications/NotificationItems/UpdateAvailableNotificationItemView.xaml @@ -8,7 +8,7 @@ xmlns:common="clr-namespace:Tango.PPC.Common.Converters" mc:Ignorable="d" x:Name="MessageNotificationItemControl" - d:DesignHeight="60" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=local:UpdateAvailableNotificationItem, IsDesignTimeCreatable=False}" MinHeight="90" Height="90" MaxHeight="150" Background="White"> + d:DesignHeight="60" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=local:UpdateAvailableNotificationItem, IsDesignTimeCreatable=False}" MinHeight="90" Height="90" MaxHeight="150" Background="{StaticResource TangoPrimaryBackgroundBrush}"> diff --git a/Software/Visual_Studio/Tango.Touch/Controls/TouchNotificationBar.cs b/Software/Visual_Studio/Tango.Touch/Controls/TouchNotificationBar.cs index ef7e24ff4..ccd27333a 100644 --- a/Software/Visual_Studio/Tango.Touch/Controls/TouchNotificationBar.cs +++ b/Software/Visual_Studio/Tango.Touch/Controls/TouchNotificationBar.cs @@ -165,8 +165,7 @@ namespace Tango.Touch.Controls { element.RegisterForLoadedOrNow((x, y) => { - CurrentMinHeight = element.ActualHeight; - ResizeNotification(element); + CurrentMinHeight = element.FindChild().MinHeight; }); } } @@ -250,10 +249,25 @@ namespace Tango.Touch.Controls if (Notifications is INotifyCollectionChanged) { - (Notifications as INotifyCollectionChanged).CollectionChanged += (_, __) => + (Notifications as INotifyCollectionChanged).CollectionChanged += (_, e) => { this.BeginInvoke(() => { + if (e.NewItems != null && e.NewItems.Count > 0) + { + foreach (var item in e.NewItems.Cast().ToList()) + { + var element = _items_control.ItemContainerGenerator.ContainerFromItem(item) as FrameworkElement; + if (element != null) + { + element.RegisterForLoadedOrNow((___, ____) => + { + ResizeNotification(element); + }); + } + } + } + UpdateExpanded(IsExpanded); }); }; diff --git a/Software/Visual_Studio/Tango.Transport/Web/StandardFileDownloader.cs b/Software/Visual_Studio/Tango.Transport/Web/StandardFileDownloader.cs index d254abd96..1b62fc023 100644 --- a/Software/Visual_Studio/Tango.Transport/Web/StandardFileDownloader.cs +++ b/Software/Visual_Studio/Tango.Transport/Web/StandardFileDownloader.cs @@ -23,6 +23,7 @@ namespace Tango.Transport.Web Address = address; FileName = fileName; _client = new WebClient(); + _client.Proxy = null; _client.DownloadProgressChanged += _client_DownloadProgressChanged; _client.DownloadFileCompleted += _client_DownloadFileCompleted; -- cgit v1.3.1 From c7fa53084c674586ceee773ccbdc6b4c0a2ec7d4 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Mon, 9 Dec 2019 16:19:41 +0200 Subject: Implemented full TUP package update !!! --- .../FirmwareUpgrade/VersionFileDescriptor.proto | 1 - .../Tango.MachineStudio.MachineDesigner.csproj | 8 + .../ViewModels/MainViewVM.cs | 8 + .../ViewModels/TupViewVM.cs | 129 ++++++ .../Views/MachineDetailsView.xaml | 3 + .../Views/TupView.xaml | 60 +++ .../Views/TupView.xaml.cs | 28 ++ .../Tango.MachineStudio.Common.csproj | 17 +- .../Tup/TupFileBuilder.cs | 285 +++++++++++++ .../Tup/TupFileBuilderProgressEventArgs.cs | 16 + .../Web/DownloadLatestPPCVersionRequest.cs | 14 + .../Web/DownloadLatestPPCVersionResponse.cs | 21 + .../Web/MachineStudioWebClientBase.cs | 9 + .../Tango.MachineStudio.Common/packages.config | 1 + .../Tango.MachineStudio.UI.csproj | 6 +- .../MachineUpdate/IMachineUpdateManager.cs | 7 +- .../MachineUpdate/MachineUpdateManager.cs | 468 ++++++++++++++++++--- .../MachineUpdate/MachineUpdateResult.cs | 13 + .../MachineUpdate/UpdatePackageFile.cs | 13 - .../PPC/Tango.PPC.Common/Publish/PublishInfo.cs | 6 +- .../PPC/Tango.PPC.Common/Tango.PPC.Common.csproj | 1 - .../Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml | 12 +- .../Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs | 30 +- .../PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml | 5 +- Software/Visual_Studio/Tango.Core/DB/DbManager.cs | 33 +- .../FirmwareUpgrade/VersionFileDescriptor.cs | 37 +- .../ExaminerSequenceConfigurationRunner.cs | 9 + .../Tango.SQLExaminer/ExtensionMethods.cs | 21 + Software/Visual_Studio/Tango.SQLExaminer/Helper.cs | 2 +- .../Tango.SQLExaminer/Tango.SQLExaminer.csproj | 1 + .../SQLExaminer/SQLExaminer_TST.cs | 71 ++++ .../Controllers/MachineStudioController.cs | 65 +++ .../Controllers/PPCController.cs | 2 +- 33 files changed, 1257 insertions(+), 145 deletions(-) create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/TupViewVM.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml.cs create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilder.cs create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilderProgressEventArgs.cs create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionRequest.cs create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionResponse.cs delete mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/UpdatePackageFile.cs create mode 100644 Software/Visual_Studio/Tango.SQLExaminer/ExtensionMethods.cs (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/PMR/Messages/FirmwareUpgrade/VersionFileDescriptor.proto b/Software/PMR/Messages/FirmwareUpgrade/VersionFileDescriptor.proto index ce44290a0..9e74cdee6 100644 --- a/Software/PMR/Messages/FirmwareUpgrade/VersionFileDescriptor.proto +++ b/Software/PMR/Messages/FirmwareUpgrade/VersionFileDescriptor.proto @@ -10,5 +10,4 @@ message VersionFileDescriptor string FileName = 1; string Version = 2; VersionFileDestination Destination = 3; - bytes CheckSum = 4; } \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Tango.MachineStudio.MachineDesigner.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Tango.MachineStudio.MachineDesigner.csproj index 6225bd7ad..69cc75461 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Tango.MachineStudio.MachineDesigner.csproj +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Tango.MachineStudio.MachineDesigner.csproj @@ -93,6 +93,7 @@ + ColorCalibrationView.xaml @@ -130,6 +131,9 @@ MachineUpdatesView.xaml + + TupView.xaml + SpoolsView.xaml @@ -185,6 +189,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + Designer MSBuild:Compile diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MainViewVM.cs index 820950290..768f93de1 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MainViewVM.cs @@ -140,6 +140,12 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels set { _machineUpdatesViewVM = value; RaisePropertyChangedAuto(); } } + private TupViewVM _tupViewVM; + public TupViewVM TupViewVM + { + get { return _tupViewVM; } + set { _tupViewVM = value; RaisePropertyChangedAuto(); } + } #endregion @@ -233,6 +239,7 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels ResetDeviceRegistrationCommand = new RelayCommand(ResetDeviceRegistration); MachineUpdatesViewVM = new MachineUpdatesViewVM(_notification); + TupViewVM = new TupViewVM(_notification); } #endregion @@ -478,6 +485,7 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels HardwareConfigurationViewVM.Init(ActiveMachine.Configuration); await MachineUpdatesViewVM.Init(ActiveMachine, ActiveMachineAdapter.Context); + TupViewVM.Init(ActiveMachine); ActiveMachine.Configuration.HardwareVersionChanged += Configuration_HardwareVersionChanged; diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/TupViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/TupViewVM.cs new file mode 100644 index 000000000..12ed09c75 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/TupViewVM.cs @@ -0,0 +1,129 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; +using Tango.Core.Commands; +using Tango.MachineStudio.Common.Notifications; +using Tango.MachineStudio.Common.Tup; +using Tango.SharedUI; + +namespace Tango.MachineStudio.MachineDesigner.ViewModels +{ + public class TupViewVM : ViewModel + { + private INotificationProvider _notification; + + private String _latestVersion; + public String LatestVersion + { + get { return _latestVersion; } + set { _latestVersion = value; RaisePropertyChangedAuto(); } + } + + private Machine _machine; + public Machine Machine + { + get { return _machine; } + set { _machine = value; RaisePropertyChangedAuto(); } + } + + private String _filePath; + public String FilePath + { + get { return _filePath; } + set { _filePath = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + private TupFileBuilderProgressEventArgs _progress; + public TupFileBuilderProgressEventArgs Progress + { + get { return _progress; } + set { _progress = value; RaisePropertyChangedAuto(); } + } + + public RelayCommand CreateTupFileCommand { get; set; } + + public RelayCommand SelectFileCommand { get; set; } + + public TupViewVM() + { + + } + + public TupViewVM(INotificationProvider notification) : this() + { + _notification = notification; + CreateTupFileCommand = new RelayCommand(CreateTupFile, () => FilePath != null && IsFree); + SelectFileCommand = new RelayCommand(SelectFile); + } + + public void Init(Machine machine) + { + Machine = machine; + DisplayLatestPPCVersion(); + } + + private async void DisplayLatestPPCVersion() + { + TupFileBuilder builder = new TupFileBuilder(); + + try + { + LatestVersion = await builder.GetLatestPPCVersion(Machine.SerialNumber); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error retrieving latest PPC version."); + await Task.Delay(5000); + DisplayLatestPPCVersion(); + } + } + + private void SelectFile() + { + SaveFileDialog dlg = new SaveFileDialog(); + dlg.Title = "Select package location"; + dlg.Filter = "Tango Update Package Files|*.tup"; + dlg.DefaultExt = ".tup"; + dlg.FileName = LatestVersion == null ? $"{Machine.SerialNumber}_Update.tup" : $"{Machine.SerialNumber}_Update_v{LatestVersion}.tup"; + + if (dlg.ShowDialog().Value) + { + FilePath = dlg.FileName; + } + } + + private async void CreateTupFile() + { + try + { + LogManager.Log($"Generating TUP file to '{FilePath}'..."); + + IsFree = false; + TupFileBuilder builder = new TupFileBuilder(); + builder.Progress += Builder_Progress; + await builder.Build(Machine.SerialNumber, FilePath); + + LogManager.Log("TUP file generated successfully."); + _notification.ShowInfo("Tango update package created successfuly."); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error generating tup file."); + _notification.ShowError($"An error occurred while generating the .tup file.\n{ex.FlattenMessage()}"); + } + finally + { + IsFree = true; + } + } + + private void Builder_Progress(object sender, TupFileBuilderProgressEventArgs e) + { + Progress = e; + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineDetailsView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineDetailsView.xaml index 666a4ee4a..bcca83ca5 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineDetailsView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineDetailsView.xaml @@ -64,6 +64,9 @@ + + + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml new file mode 100644 index 000000000..895a26ca0 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + Create a complete update package (.tup) in order to update this machine offline using a removable storage device. + + The latest PPC version is + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml.cs new file mode 100644 index 000000000..fe01296d8 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.MachineStudio.MachineDesigner.Views +{ + /// + /// Interaction logic for SpoolsView.xaml + /// + public partial class TupView : UserControl + { + public TupView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj index 7c0851d01..3ce667afe 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj @@ -59,6 +59,9 @@ ..\..\Referenced Assemblies\SMO\Microsoft.SqlServer.AzureStorageEnum.dll + + ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + @@ -83,6 +86,9 @@ + + Tup\PublishInfo.cs + GlobalVersionInfo.cs @@ -95,6 +101,10 @@ + + + + @@ -291,6 +301,10 @@ {8491d07b-c1f6-4b62-a412-41b9fd2d6538} Tango.SharedUI + + {e1e66ed9-597d-45fa-8048-de90a6930484} + Tango.SQLExaminer + {74e700b0-1156-4126-be40-ee450d3c3026} Tango.Transport @@ -387,10 +401,11 @@ + - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilder.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilder.cs new file mode 100644 index 000000000..6dd8b82f7 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilder.cs @@ -0,0 +1,285 @@ +using Ionic.Zip; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Tango.BL; +using Tango.Core; +using Tango.Core.DB; +using Tango.Core.DI; +using Tango.MachineStudio.Common.Web; +using Tango.SQLExaminer; +using Tango.Transport.Web; +using Tango.Core.ExtensionMethods; +using Tango.PPC.Common.Publish; +using Tango.Settings; +using Tango.Core.Components; +using System.Text.RegularExpressions; + +namespace Tango.MachineStudio.Common.Tup +{ + public class TupFileBuilder : ExtendedObject + { + public event EventHandler Progress; + + public Task Build(String serialNumber, String filePath) + { + return Task.Factory.StartNew(() => + { + String tempDbName = "Tango_TUP"; + var tempPackageFolder = TemporaryManager.CreateFolder(); + String tempBackupFolder = "C:\\MachineStudioTUP"; + String tempBackupFile = Path.Combine(tempBackupFolder, tempDbName + ".bak"); + var tempZipFile = TemporaryManager.CreateImaginaryFile(); + DbManager dbManager = null; + + LogManager.Log("Generating tup file..."); + LogManager.Log($"Tup file: '{filePath}.'"); + LogManager.Log($"Temporary db name: '{tempDbName}'."); + LogManager.Log($"Temporary package folder: '{tempPackageFolder}'."); + LogManager.Log($"Temporary db backup folder: '{tempBackupFolder}'."); + LogManager.Log($"Temporary db backup file: '{tempBackupFile}'."); + LogManager.Log($"Temporary zip file: '{tempZipFile}'."); + + try + { + LogManager.Log("Initializing..."); + + OnProgress("Initializing..."); + + Core.DataSource localDataSource = new Core.DataSource() + { + Address = "localhost\\SQLEXPRESS", + IntegratedSecurity = true, + Type = DataSourceType.SQLServer, + Catalog = null, + }; + + try + { + LogManager.Log($"Trying to connect via SQLEXPRESS:\n{localDataSource.ToJsonString()}"); + dbManager = DbManager.FromDataSource(localDataSource); + } + catch (Exception ex) + { + try + { + LogManager.Log(ex, "Could not connect using SQLEXPRESS. Trying local DB..."); + + CmdCommand command = new CmdCommand("sqllocaldb", "info \"MSSQLLocalDB\""); + var result = command.Run().Result; + + String pattern = "np:.+"; + Regex reg = new Regex(pattern); + var match = reg.Match(result.StandardOutput); + String address = match.ToString(); + if (address.Contains("np:")) + { + localDataSource.Address = address; + address = address.Trim().Replace("\r", ""); + } + else + { + throw new ArgumentException("Could not parse LocalDB address string."); + } + + LogManager.Log($"Trying to connect via LocalDB:\n{localDataSource.ToJsonString()}"); + dbManager = DbManager.FromDataSource(localDataSource); + } + catch (Exception x) + { + LogManager.Log(x, "Could not find any database service for this operation."); + throw x; + } + } + + + + OnProgress("Downloading latest PPC version..."); + + LogManager.Log("Connecting to machine service..."); + MachineStudioWebClient client = TangoIOC.Default.GetInstance(); + + LogManager.Log("Requesting latest PPC version from machine service..."); + var response = client.DownloadLatestPPCVersion(new DownloadLatestPPCVersionRequest() { SerialNumber = serialNumber }).Result; + + LogManager.Log($"Machine service response:\n{response.ToJsonString()}"); + + var remoteDataSource = response.DataSource; + + using (AutoFileDownloader downloader = new AutoFileDownloader(response.BlobAddress, response.CdnAddress, tempZipFile)) + { + downloader.Progress += (x, e) => + { + OnProgress($"Downloading latest PPC version '{response.Version}'...", false, e.Current, e.Total); + }; + + downloader.ResolveMode().GetAwaiter().GetResult(); + + LogManager.Log($"Downloading latest PPC version from: '{downloader.Address}'"); + + downloader.Download().Wait(); + } + + LogManager.Log("Extracting PPC version package..."); + + OnProgress("Extracting PPC package..."); + + using (ZipFile zip = new ZipFile(tempZipFile)) + { + int currentEntry = 0; + + zip.ExtractProgress += (x, args) => + { + if (args.EventType == ZipProgressEventType.Extracting_AfterExtractEntry) + { + OnProgress("Extracting PPC package...", false, currentEntry++, zip.Entries.Count); + } + }; + + zip.ExtractAll(tempPackageFolder); + } + + OnProgress("Extracting version information..."); + LogManager.Log("Extracting publish information..."); + PublishInfo publishInfo = PublishInfo.FromJson(File.ReadAllText(Path.Combine(tempPackageFolder, "version.json"))); + LogManager.Log($"Publish Information:\n{publishInfo}"); + + LogManager.Log("Modifying publish information to custom tup file..."); + publishInfo.IsMachineTupPackage = true; + publishInfo.MachineSerialNumber = serialNumber; + publishInfo.MachineDeploymentSlot = SettingsManager.Default.GetOrCreate().DeploymentSlot; + + OnProgress("Creating temporary database..."); + + LogManager.Log($"Creating temporary db backup directory '{tempBackupFolder}'"); + + Directory.CreateDirectory(tempBackupFolder); + + LogManager.Log($"Creating new database: '{tempDbName}'"); + + //Create temp db + dbManager.Create(tempDbName, Path.Combine(tempBackupFolder, tempDbName + ".mdf")); + + OnProgress("Generating database snapshot..."); + + LogManager.Log("Starting database synchronization..."); + + Thread.Sleep(2000); + + localDataSource.Catalog = tempDbName; + + ExaminerSequenceConfigurationRunner runner = new ExaminerSequenceConfigurationRunner( + Path.Combine(tempPackageFolder, "Provision Scripts", "config.xml"), + Path.Combine(tempPackageFolder, "Provision Scripts"), + remoteDataSource, + localDataSource, + serialNumber); + + runner.ScriptExecuting += (x, item) => + { + LogManager.Log($"Executing script '{item.FileName}'..."); + OnProgress($"{item.Name}..."); + }; + + runner.Log += (x, log) => + { + LogManager.Log(log); + }; + + runner.Run().GetAwaiter().GetResult(); + + OnProgress("Generating database snapshot..."); + + if (File.Exists(tempBackupFile)) + { + LogManager.Log($"Deleting file '{tempBackupFile}'"); + File.Delete(tempBackupFile); + } + + LogManager.Log($"Generating backup for '{tempDbName}' to '{tempBackupFile}'..."); + + dbManager.Backup(tempDbName, tempBackupFile); + + OnProgress("Injecting database snapshot to PPC package..."); + + using (ZipFile zip = new ZipFile(tempZipFile)) + { + LogManager.Log($"Injecting file '{tempBackupFile}' to original package at '{tempZipFile}'..."); + zip.AddFile(tempBackupFile, "/"); + + LogManager.Log($"Injecting modified publish information..."); + zip.UpdateEntry("version.json", publishInfo.ToJson()); + + zip.Save(); + } + + LogManager.Log($"Copying '{tempZipFile}' to '{filePath}'..."); + + File.Copy(tempZipFile, filePath, true); + + OnProgress("Completed", false, 100, 100); + + LogManager.Log("TUP file generation completed successfully."); + } + catch (Exception ex) + { + LogManager.Log(ex, "TUP file generation failed."); + OnProgress("Failed", false, 0, 100); + throw ex; + } + finally + { + LogManager.Log($"Removing '{tempZipFile}'."); + tempZipFile.Delete(); + LogManager.Log($"Removing '{tempPackageFolder}'."); + tempPackageFolder.Delete(); + + try + { + LogManager.Log($"Removing database '{tempDbName}'."); + dbManager.SetOffline(tempDbName); + dbManager.SetOnline(tempDbName); + dbManager.Delete(tempDbName); + dbManager.Dispose(); + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error removing temp database '{tempDbName}'."); + } + + try + { + LogManager.Log($"Removing '{tempBackupFolder}'."); + Directory.Delete(tempBackupFolder, true); + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error removing folder '{tempBackupFolder}'."); + } + } + }); + } + + public async Task GetLatestPPCVersion(String serialNumber) + { + MachineStudioWebClient client = TangoIOC.Default.GetInstance(); + var response = await client.DownloadLatestPPCVersion(new DownloadLatestPPCVersionRequest() { SerialNumber = serialNumber }); + return response.Version; + } + + private void OnProgress(String message, bool isIntermediate = true, double progress = 0, double total = 100) + { + Progress?.Invoke(this, new TupFileBuilderProgressEventArgs() + { + Message = message, + IsIntermediate = isIntermediate, + Progress = progress, + Total = total, + }); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilderProgressEventArgs.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilderProgressEventArgs.cs new file mode 100644 index 000000000..ada69dd40 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilderProgressEventArgs.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.MachineStudio.Common.Tup +{ + public class TupFileBuilderProgressEventArgs + { + public double Progress { get; set; } + public double Total { get; set; } + public bool IsIntermediate { get; set; } + public String Message { get; set; } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionRequest.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionRequest.cs new file mode 100644 index 000000000..24d465e69 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionRequest.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.MachineStudio.Common.Web +{ + public class DownloadLatestPPCVersionRequest : WebRequestMessage + { + public String SerialNumber { get; set; } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionResponse.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionResponse.cs new file mode 100644 index 000000000..2cc6b731a --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionResponse.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Transport.Web; + +namespace Tango.MachineStudio.Common.Web +{ + public class DownloadLatestPPCVersionResponse : WebResponseMessage + { + public String Version { get; set; } + + public String BlobAddress { get; set; } + + public String CdnAddress { get; set; } + + public DataSource DataSource { get; set; } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs index 131f89515..c2d0dd3e6 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs @@ -94,5 +94,14 @@ namespace Tango.MachineStudio.Common.Web return Post("RefreshToken", request); } + /// + /// Executes the DownloadLatestPPCVersion action and returns Tango.MachineStudio.Common.Web.DownloadLatestPPCVersionResponse. + /// + /// + public Task DownloadLatestPPCVersion(Tango.MachineStudio.Common.Web.DownloadLatestPPCVersionRequest request) + { + return Post("DownloadLatestPPCVersion", request); + } + } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/packages.config b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/packages.config index f871776f5..6fd5091a8 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/packages.config +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/packages.config @@ -9,4 +9,5 @@ + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index 991eb9da6..c6cf624b3 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -448,6 +448,10 @@ {8491d07b-c1f6-4b62-a412-41b9fd2d6538} Tango.SharedUI + + {e1e66ed9-597d-45fa-8048-de90a6930484} + Tango.SQLExaminer + {998f8471-dc1b-41b6-9d96-354e1b4e7a32} Tango.TFS @@ -661,7 +665,7 @@ if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)ProtoCompilers\" - + \ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs index 3655aa462..e11eab3a5 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.PMR.Synchronization; +using Tango.PPC.Common.Publish; using Tango.PPC.Common.UpdatePackages; using Tango.PPC.Common.Web; @@ -43,14 +44,14 @@ namespace Tango.PPC.Common.MachineUpdate /// if set to true updates the embedded device firmware. /// if set to true updates the embedded device FPGA version and other parameters. /// - Task Update(String serialNumber, bool setupFirmware, bool setupFPGA); + Task Update(bool setupFirmware, bool setupFPGA); /// /// Performs a machine update using the specified software update package path. /// /// Name of the file. /// - Task UpdateFromTUP(String fileName); + Task UpdateFromTUP(String fileName, bool setupFirmware, bool setupFPGA); /// /// Checks if any update are available for the specified machine serial number. @@ -77,7 +78,7 @@ namespace Tango.PPC.Common.MachineUpdate /// /// The file path. /// - Task GetUpdatePackageFileInfo(String filePath); + Task GetUpdatePackageFileInfo(String filePath); /// /// Checks whether any post update packages needs to be installed. diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs index 5296a9f34..7e742ceb6 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs @@ -22,6 +22,7 @@ using Tango.PMR.Synchronization; using Tango.PPC.Common.Application; using Tango.PPC.Common.Connection; using Tango.PPC.Common.Navigation; +using Tango.PPC.Common.Publish; using Tango.PPC.Common.UpdatePackages; using Tango.PPC.Common.Web; using Tango.Settings; @@ -117,7 +118,10 @@ namespace Tango.PPC.Common.MachineUpdate private void LogManager_NewLog(object sender, LogItemBase e) { - _logs.Add(e); + if (_isUpdating) + { + _logs.Add(e); + } } #endregion @@ -133,37 +137,80 @@ namespace Tango.PPC.Common.MachineUpdate }); } - private async void OnFailed(Exception ex, TaskCompletionSource completionSource, DownloadUpdateResponse response, bool performDatabaseRollback, String dbBackupFile, Tango.Core.DataSource localDataSource) + private async void OnFailed(Exception ex, TaskCompletionSource completionSource, DownloadUpdateResponse response, bool performDatabaseRollback, String dbBackupFile, String backupsFolder, String tempDbName, Tango.Core.DataSource localDataSource, String tempUpdatePackageFolder = null) { LogManager.Log(ex, "An error occurred in machine update."); - if (performDatabaseRollback) + await Task.Factory.StartNew(() => { - LogManager.Log("Rolling back database changes..."); - using (DbManager db = DbManager.FromDataSource(localDataSource)) + if (performDatabaseRollback) + { + LogManager.Log("Rolling back database changes..."); + + using (DbManager db = DbManager.FromDataSource(localDataSource)) + { + try + { + UpdateProgress("Rollback", "Rolling back database changes..."); + db.Restore(localDataSource.Catalog, dbBackupFile); + LogManager.Log("Database restored successfully."); + } + catch (Exception e) + { + LogManager.Log(e, "Could not rollback the database."); + } + finally + { + try + { + File.Delete(dbBackupFile); + } + catch { } + } + } + } + + if (tempDbName != null) { try { - UpdateProgress("Rollback", "Rolling back database changes..."); - await Task.Factory.StartNew(() => db.Restore(localDataSource.Catalog, dbBackupFile)); - LogManager.Log("Database restored successfully."); + LogManager.Log($"Removing temporary database '{tempDbName}'..."); + using (DbManager dbManager = DbManager.FromDataSource(localDataSource)) + { + dbManager.SetOffline(tempDbName); + dbManager.SetOnline(tempDbName); + dbManager.Delete(tempDbName); + } } - catch (Exception e) + catch (Exception exx) { - LogManager.Log(e, "Could not rollback the database."); - throw ex; + LogManager.Log(exx, "Error removing temporary database."); } - finally + } + + try + { + Directory.Delete(backupsFolder, true); + } + catch (Exception ee) + { + LogManager.Log(ee, $"Error deleting backups folder '{backupsFolder}'."); + } + + if (tempUpdatePackageFolder != null) + { + try { - try - { - File.Delete(dbBackupFile); - } - catch { } + Directory.Delete(tempUpdatePackageFolder, true); + } + catch (Exception eee) + { + LogManager.Log(eee, "Error removing temporary package folder."); } } - } + + }); completionSource.SetException(ex); @@ -188,13 +235,50 @@ namespace Tango.PPC.Common.MachineUpdate _isUpdating = false; } - private async void OnCompleted(MachineUpdateResult result, TaskCompletionSource completionSource, DownloadUpdateResponse response, String dbBackupFile) + private async void OnCompleted(MachineUpdateResult result, TaskCompletionSource completionSource, DownloadUpdateResponse response, String tempDbName, String backupsFolder, Core.DataSource localDataSource) { - try + await Task.Factory.StartNew(() => { - File.Delete(dbBackupFile); - } - catch { } + if (tempDbName != null) + { + try + { + LogManager.Log($"Removing temporary database '{tempDbName}'..."); + using (DbManager dbManager = DbManager.FromDataSource(localDataSource)) + { + dbManager.SetOffline(tempDbName); + dbManager.SetOnline(tempDbName); + dbManager.Delete(tempDbName); + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error removing temporary database."); + } + } + + try + { + Directory.Delete(backupsFolder, true); + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error deleting backups folder '{backupsFolder}'."); + } + + if (!result.RequiresBinariesUpdate) + { + try + { + Directory.Delete(result.UpdatePackagePath, true); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error removing temporary package folder."); + } + } + + }); completionSource.SetResult(result); @@ -315,7 +399,7 @@ namespace Tango.PPC.Common.MachineUpdate /// or /// /// Database tango does not exists. - public async Task Update(String serialNumber, bool setupFirmware, bool setupFPGA) + public async Task Update(bool setupFirmware, bool setupFPGA) { _logs.Clear(); @@ -325,6 +409,13 @@ namespace Tango.PPC.Common.MachineUpdate bool performDatabaseRollback = false; String dbBackupFile = null; DownloadUpdateResponse update_response = null; + String backupsFolder = "C:\\Backups"; + + //Create temporary folders for packages. + var _newPackageTempFolder = TemporaryManager.CreateFolder(); + _newPackageTempFolder.Persist = true; + + String serialNumber = _machineProvider.Machine.SerialNumber; try { @@ -371,10 +462,6 @@ namespace Tango.PPC.Common.MachineUpdate LogManager.Log($"Machine update response received: {Environment.NewLine}{update_response.ToJsonString()}"); - //Create temporary folders for packages. - var _newPackageTempFolder = TemporaryManager.CreateFolder(); - _newPackageTempFolder.Persist = true; - LogManager.Log($"Temporary package folder created: {_newPackageTempFolder}."); //Download software package. @@ -413,8 +500,12 @@ namespace Tango.PPC.Common.MachineUpdate UpdateProgress("Downloading software package", "Extracting package..."); LogManager.Log("Extracting downloaded zip file..."); - //Extract software package. - ZipFile.ExtractToDirectory(tempFile, _newPackageTempFolder); + + await Task.Factory.StartNew(() => + { + //Extract software package. + ZipFile.ExtractToDirectory(tempFile, _newPackageTempFolder); + }); LogManager.Log("Copying latest updater utility to application path..."); //Copy new updater utility to app path. @@ -464,8 +555,8 @@ namespace Tango.PPC.Common.MachineUpdate //Create Database Backup try { - Directory.CreateDirectory("C:\\Backups"); - dbBackupFile = $"C:\\Backups\\{Path.GetRandomFileName()}.bak"; + Directory.CreateDirectory(backupsFolder); + dbBackupFile = $"{backupsFolder}\\{Path.GetRandomFileName()}.bak"; LogManager.Log($"Creating database backup to '{dbBackupFile}'..."); await Task.Factory.StartNew(() => db.Backup(localDataSource.Catalog, dbBackupFile)); performDatabaseRollback = true; @@ -548,7 +639,7 @@ namespace Tango.PPC.Common.MachineUpdate handler.Failed += (_, ex) => { stream.Dispose(); - OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, localDataSource); + OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, backupsFolder, null, localDataSource, _newPackageTempFolder); }; handler.Completed += (_, __) => { @@ -557,12 +648,12 @@ namespace Tango.PPC.Common.MachineUpdate OnCompleted(new MachineUpdateResult() { UpdatePackagePath = _newPackageTempFolder, - }, result, update_response, dbBackupFile); + }, result, update_response, null, backupsFolder, localDataSource); }; handler.Canceled += (_, __) => { stream.Dispose(); - OnFailed(new Exception("The operation has been canceled."), result, update_response, performDatabaseRollback, dbBackupFile, localDataSource); + OnFailed(new Exception("The operation has been canceled."), result, update_response, performDatabaseRollback, dbBackupFile, backupsFolder, null, localDataSource, _newPackageTempFolder); }; handler.Progress += (_, e) => { @@ -574,12 +665,12 @@ namespace Tango.PPC.Common.MachineUpdate OnCompleted(new MachineUpdateResult() { UpdatePackagePath = _newPackageTempFolder, - }, result, update_response, dbBackupFile); + }, result, update_response, null, backupsFolder, localDataSource); } } catch (Exception ex) { - OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, localDataSource); + OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, backupsFolder, null, localDataSource, _newPackageTempFolder); } return await result.Task; @@ -875,31 +966,284 @@ namespace Tango.PPC.Common.MachineUpdate /// /// Name of the file. /// - public Task UpdateFromTUP(string fileName) + public async Task UpdateFromTUP(string fileName, bool setupFirmware, bool setupFPGA) { - return Task.Factory.StartNew(() => + _logs.Clear(); + + TaskCompletionSource result = new TaskCompletionSource(); + + var localDataSource = SettingsManager.Default.GetOrCreate().DataSource; + bool performDatabaseRollback = false; + String dbBackupFile = null; + String tempDbName = "Tango_TUP"; + String tempDbFileName = tempDbName + ".bak"; + String backupsFolder = "C:\\Backups"; + bool replaceBinaries = false; + + String serialNumber = _machineProvider.Machine.SerialNumber; + + //Create temporary folders for packages. + var _newPackageTempFolder = TemporaryManager.CreateFolder(); + _newPackageTempFolder.Persist = true; + + try { - LogManager.Log($"Starting machine update from update package '{fileName}'..."); + _isUpdating = true; + + LogManager.Log($"Starting machine update for serial number {serialNumber}..."); - //Create temporary folders for packages. - var _newPackageTempFolder = TemporaryManager.CreateFolder(); - _newPackageTempFolder.Persist = true; + //Connecting to machine... + LogManager.Log("Verifying machine connection and state..."); - LogManager.Log("Extracting downloaded zip file..."); - //Extract software package. - ZipFile.ExtractToDirectory(fileName, _newPackageTempFolder); + UpdateProgress("Verifying machine state", "Initializing..."); + + await Task.Delay(1000); + + IMachineOperator op = _machineProvider.MachineOperator; + + if (setupFirmware) + { + LogManager.Log("Machine is configured to update firmware..."); + + if (op.State != Transport.TransportComponentState.Connected) + { + throw LogManager.Log(new InvalidOperationException("Could not perform an update while the machine is not connected.")); + } + if (op.Status != MachineStatuses.ReadyToDye) + { + throw LogManager.Log(new InvalidOperationException($"Could not perform an update while the machine is in {op.Status} status.")); + } + } + + UpdateProgress("Exploring package", "Extracting..."); + LogManager.Log("Extracting package..."); + + LogManager.Log($"Temporary package folder created: {_newPackageTempFolder}."); + + await Task.Factory.StartNew(() => + { + //Extract software package. + ZipFile.ExtractToDirectory(fileName, _newPackageTempFolder); + }); + + //Extracting publish info + UpdateProgress("Exploring package", "Verifying..."); + PublishInfo publishInfo = PublishInfo.FromJson(File.ReadAllText(Path.Combine(_newPackageTempFolder, "version.json"))); + + if (!publishInfo.IsMachineTupPackage) + { + throw new InvalidOperationException("The specified tup file is invalid. Updating a machine from a tup file requires a custom generated package."); + } + + if (publishInfo.MachineSerialNumber != serialNumber) + { + throw new InvalidOperationException("The specified tup file is invalid. The package was generated for a different machine."); + } + + if (publishInfo.MachineDeploymentSlot != SettingsManager.Default.GetOrCreate().DeploymentSlot) + { + throw new InvalidOperationException("The specified tup file is invalid. The package was generated on a different environment."); + } + + replaceBinaries = _app_manager.Version.ToString() != publishInfo.ApplicationVersion; LogManager.Log("Copying latest updater utility to application path..."); + //Copy new updater utility to app path. File.Copy(Path.Combine(_newPackageTempFolder, "Tango.PPC.Updater.exe"), Path.Combine(PathHelper.GetStartupPath(), "Tango.PPC.Updater.exe"), true); - LogManager.Log("Update operation completed!"); + //Run pre-update packages. + try + { + UpdateProgress("Preparing", "Running update packages..."); + LogManager.Log("Running pre-update packages..."); + var packagesFolder = Path.Combine(_newPackageTempFolder, "Packages"); - return new MachineUpdateResult() + Version updateVersion = new Version(1, 0, 0, 0); + try + { + updateVersion = Version.Parse(publishInfo.ApplicationVersion); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error parsing new version string for package runner."); + } + + await _packageRunner.Run(PackageType.Pre, updateVersion, packagesFolder); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error running pre-update packages..."); + } + + //Synchronize database + UpdateProgress("Updating Database", "Initializing..."); + + UpdateProgress("Updating Database", "Connecting to local database..."); + LogManager.Log("Initializing database manager..."); + DbManager db = DbManager.FromDataSource(localDataSource); + + LogManager.Log("Checking Tango database exists on the local machine..."); + if (!db.Exists(localDataSource.Catalog)) + { + throw new InvalidProgramException("Database tango does not exists."); + } + + UpdateProgress("Updating Database", "Creating database backup..."); + + //Create Database Backup + try + { + Directory.CreateDirectory(backupsFolder); + dbBackupFile = $"{backupsFolder}\\{Path.GetRandomFileName()}.bak"; + LogManager.Log($"Creating database backup to '{dbBackupFile}'..."); + await Task.Factory.StartNew(() => db.Backup(localDataSource.Catalog, dbBackupFile)); + performDatabaseRollback = true; + LogManager.Log("Database backup created successfully."); + } + catch (Exception ex) + { + throw LogManager.Log(ex, "Update manager error while trying to create a database backup."); + } + + LogManager.Log("Extracting database file from package..."); + File.Copy(Path.Combine(_newPackageTempFolder, tempDbFileName), Path.Combine(backupsFolder, tempDbFileName)); + + LogManager.Log("Restoring package database as a new database..."); + db.RestoreAsNew(tempDbName, Path.Combine(backupsFolder, tempDbFileName), backupsFolder); + + Core.DataSource tempDbDataSource = new Core.DataSource(); + tempDbDataSource.Address = localDataSource.Address; + tempDbDataSource.IntegratedSecurity = localDataSource.IntegratedSecurity; + tempDbDataSource.Type = localDataSource.Type; + tempDbDataSource.Catalog = tempDbName; + + LogManager.Log("Disposing database manager."); + db.Dispose(); + + LogManager.Log($"Initializing {nameof(ExaminerSequenceConfigurationRunner)}..."); + + UpdateProgress("Updating Database", "Initializing update sequence..."); + + ExaminerSequenceConfigurationRunner runner = new ExaminerSequenceConfigurationRunner( + Path.Combine(_newPackageTempFolder, "Update Scripts", "config.xml"), + Path.Combine(_newPackageTempFolder, "Update Scripts"), + tempDbDataSource, + localDataSource, + serialNumber); + + runner.Log += (x, msg) => { - UpdatePackagePath = _newPackageTempFolder, + LogManager.Log(msg); + ProgressLog?.Invoke(this, msg); }; - }); + + runner.ScriptExecuting += (x, item) => + { + LogManager.Log($"Executing script {item.ToString()}..."); + UpdateProgress("Updating Database", item.Name + "..."); + }; + + LogManager.Log("Starting synchronization process..."); + + try + { + await runner.Run(); + LogManager.Log("Synchronization completed successfully!"); + UpdateProgress("Updating Database", "Database synchronization completed successfully."); + } + catch (Exception ex) + { + throw LogManager.Log(ex, "Update manager error while trying to synchronize database."); + } + + LogManager.Log("Getting setup firmware/fpga directly from db.."); + + using (var dbManager = DbManager.FromDataSource(localDataSource)) + { + try + { + String firmware = dbManager.GetValue($"SELECT TOP 1 * FROM MACHINES WHERE SERIAL_NUMBER = '{serialNumber}'", "SETUP_FIRMWARE"); + String fpga = dbManager.GetValue($"SELECT TOP 1 * FROM MACHINES WHERE SERIAL_NUMBER = '{serialNumber}'", "SETUP_FPGA"); + + setupFirmware = bool.Parse(firmware); + setupFPGA = bool.Parse(fpga); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error getting new values of SETUP_FIRMWARE and SETUP_FPGA."); + } + } + + //Updating firmware + if (setupFirmware) + { + UpdateProgress("Updating Firmware", "Connecting to firmware device..."); + LogManager.Log(""); + LogManager.Log("-------------------------------------------------------------------------"); + LogManager.Log("Updating Firmware..."); + + UpdateProgress("Updating Firmware", "Loading firmware package..."); + var tfpPath = Path.Combine(_newPackageTempFolder, "firmware_package.tfp"); + var stream = new FileStream(tfpPath, FileMode.Open); + + if (!_machineProvider.Machine.IsDemo) + { + if (setupFPGA) + { + op.FirmwareUpgradeMode = FirmwareUpgradeModes.DFU | FirmwareUpgradeModes.TFP_PACKAGE; + } + else + { + op.FirmwareUpgradeMode = FirmwareUpgradeModes.DFU; + } + } + else + { + op.FirmwareUpgradeMode = FirmwareUpgradeModes.TFP_PACKAGE; + } + + var handler = await op.UpgradeFirmware(stream); + handler.Failed += (_, ex) => + { + stream.Dispose(); + OnFailed(ex, result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder); + }; + handler.Completed += (_, __) => + { + UpdateProgress("Updating Firmware", "Firmware update completed successfully."); + stream.Dispose(); + OnCompleted(new MachineUpdateResult() + { + UpdatePackagePath = _newPackageTempFolder, + RequiresBinariesUpdate = replaceBinaries, + }, result, null, tempDbName, backupsFolder, localDataSource); + }; + handler.Canceled += (_, __) => + { + stream.Dispose(); + OnFailed(new Exception("The operation has been canceled."), result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder); + }; + handler.Progress += (_, e) => + { + UpdateProgress("Updating Firmware", e.Message, false, e.Current, e.Total); + }; + } + else + { + OnCompleted(new MachineUpdateResult() + { + UpdatePackagePath = _newPackageTempFolder, + RequiresBinariesUpdate = replaceBinaries, + }, result, null, tempDbName, backupsFolder, localDataSource); + } + } + catch (Exception ex) + { + OnFailed(ex, result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder); + } + + return await result.Task; } /// @@ -907,25 +1251,23 @@ namespace Tango.PPC.Common.MachineUpdate /// /// The file path. /// - public Task GetUpdatePackageFileInfo(string filePath) + public Task GetUpdatePackageFileInfo(string filePath) { - return Task.Factory.StartNew(() => + return Task.Factory.StartNew(() => { - UpdatePackageFile file = new UpdatePackageFile(); - var tempFolder = TemporaryManager.CreateFolder(); - using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile(filePath)) { - var appEntry = zip.Entries.SingleOrDefault(x => x.FileName == "Tango.PPC.UI.exe"); - appEntry.Extract(tempFolder); - } + var appEntry = zip.Entries.SingleOrDefault(x => x.FileName == "version.json"); + var reader = appEntry.OpenReader(); - FileVersionInfo info = FileVersionInfo.GetVersionInfo(Path.Combine(tempFolder, "Tango.PPC.UI.exe")); - file.Version = Version.Parse(info.ProductVersion); - - tempFolder.Delete(); + using (StreamReader stReader = new StreamReader(reader)) + { + String json = stReader.ReadToEnd(); + reader.Dispose(); - return file; + return PublishInfo.FromJson(json); + } + } }); } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs index 17ae394ee..85dd5b7d2 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs @@ -12,5 +12,18 @@ namespace Tango.PPC.Common.MachineUpdate /// Gets or sets the temporary update package path from which to get the last downloaded software version. /// public String UpdatePackagePath { get; set; } + + /// + /// Gets or sets a value indicating whether the application should replace it's binaries. + /// + public bool RequiresBinariesUpdate { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public MachineUpdateResult() + { + RequiresBinariesUpdate = true; + } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/UpdatePackageFile.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/UpdatePackageFile.cs deleted file mode 100644 index df496c3be..000000000 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/UpdatePackageFile.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Tango.PPC.Common.MachineUpdate -{ - public class UpdatePackageFile - { - public Version Version { get; set; } - } -} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs index 77717254e..df5690a05 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.PMR.FirmwareUpgrade; +using Tango.Web; namespace Tango.PPC.Common.Publish { @@ -13,6 +14,9 @@ namespace Tango.PPC.Common.Publish public String ApplicationVersion { get; set; } public VersionPackageDescriptor Firmware { get; set; } public String Comments { get; set; } + public bool IsMachineTupPackage { get; set; } + public String MachineSerialNumber { get; set; } + public DeploymentSlot MachineDeploymentSlot { get; set; } public PublishInfo() { @@ -24,7 +28,7 @@ namespace Tango.PPC.Common.Publish return JsonConvert.SerializeObject(this); } - public PublishInfo FromJson(String json) + public static PublishInfo FromJson(String json) { return JsonConvert.DeserializeObject(json); } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj index e3a23903e..d38b9c8e9 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj @@ -194,7 +194,6 @@ - diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml index 231f5dabb..a175b655e 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml @@ -6,16 +6,16 @@ xmlns:local="clr-namespace:Tango.PPC.UI.Dialogs" xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch" mc:Ignorable="d" - Background="{StaticResource TangoPrimaryBackgroundBrush}" d:DesignHeight="555" d:DesignWidth="560" Width="550" Height="450" d:DataContext="{d:DesignInstance Type=local:UpdateFromFileViewVM, IsDesignTimeCreatable=False}"> + Background="{StaticResource TangoPrimaryBackgroundBrush}" d:DesignHeight="555" d:DesignWidth="560" Width="570" Height="700" d:DataContext="{d:DesignInstance Type=local:UpdateFromFileViewVM, IsDesignTimeCreatable=False}"> - - CANCEL - UPDATE - + + CANCEL + UPDATE + - UPDATE PACKAGE + Tango Update Package The selected file contains a software update package. Press 'UPDATE' to start updating your system. diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs index 0371e94da..c0654f643 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs @@ -10,6 +10,7 @@ using Tango.Core.Helpers; using Tango.Explorer; using Tango.PPC.Common; using Tango.PPC.Common.MachineUpdate; +using Tango.PPC.Common.Publish; using Tango.PPC.Common.Web; using Tango.PPC.UI.Dialogs; using Tango.PPC.UI.Notifications.NotificationItems; @@ -209,7 +210,7 @@ namespace Tango.PPC.UI.ViewModels try { - _update_result = await MachineUpdateManager.Update(MachineProvider.Machine.SerialNumber, _checkUpdateResponse.SetupFirmware, _checkUpdateResponse.SetupFPGA); + _update_result = await MachineUpdateManager.Update(_checkUpdateResponse.SetupFirmware, _checkUpdateResponse.SetupFPGA); LogManager.Log("Machine update completed."); await NavigateTo(MachineUpdateView.UpdateCompletedView); } @@ -248,15 +249,15 @@ namespace Tango.PPC.UI.ViewModels { LogManager.Log("Completing machine update..."); - if (!IsDbUpdate) + if (IsDbUpdate || !_update_result.RequiresBinariesUpdate) { - String updater_exe = Path.Combine(_update_result.UpdatePackagePath, "Tango.PPC.Updater.exe"); - ApplicationManager.UpdateApplication(updater_exe, PathHelper.GetStartupPath()); + LogManager.Log("Restarting Application..."); + ApplicationManager.Restart(); } else { - LogManager.Log("Restarting Application..."); - ApplicationManager.Restart(); + String updater_exe = Path.Combine(_update_result.UpdatePackagePath, "Tango.PPC.Updater.exe"); + ApplicationManager.UpdateApplication(updater_exe, PathHelper.GetStartupPath()); } } @@ -375,7 +376,7 @@ namespace Tango.PPC.UI.ViewModels private async void HandleSoftwareUpdatePackageLoaded(ExplorerFileItem fileItem) { - UpdatePackageFile packageFile = null; + PublishInfo packageFile = null; try { @@ -383,38 +384,33 @@ namespace Tango.PPC.UI.ViewModels } catch (Exception ex) { - LogManager.Log(ex, $"Error loading update package file from {fileItem.Path}."); + LogManager.Log(ex, $"Error loading publish info from {fileItem.Path}."); await NotificationProvider.ShowError("An error occurred while trying to load the selected software update package. Please make sure the package is valid."); return; } - if (ApplicationManager.Version <= packageFile.Version) - { - await NotificationProvider.ShowError($"The selected update package (v{packageFile.Version.ToString()}) contains an older software version."); - return; - } - UpdateFromFileViewVM vm = new UpdateFromFileViewVM(); - vm.Version = packageFile.Version.ToString(); + vm.Version = packageFile.ApplicationVersion; await NotificationProvider.ShowDialog(vm); if (vm.DialogResult) { await NavigationManager.NavigateTo(Common.Navigation.NavigationView.MachineUpdateView); - await NavigateTo(MachineUpdateView.UpdateFromPackageView); + await NavigateTo(MachineUpdateView.UpdateProgressView); LogManager.Log("Starting machine update from package..."); try { - _update_result = await MachineUpdateManager.UpdateFromTUP(fileItem.Path); + _update_result = await MachineUpdateManager.UpdateFromTUP(fileItem.Path, MachineProvider.Machine.SetupFirmware, MachineProvider.Machine.SetupFpga); LogManager.Log("Machine update from package completed."); await NavigateTo(MachineUpdateView.UpdateCompletedView); } catch (Exception ex) { LogManager.Log(ex, "Machine update from package failed."); + FailedError = ex.FlattenMessage(); await NavigateTo(MachineUpdateView.UpdateFailedFromPackageView); } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml index fba8a599d..beb09be0d 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml @@ -194,8 +194,9 @@ CLOSE - - An error occurred while trying to update the machine. + + Update Failed + diff --git a/Software/Visual_Studio/Tango.Core/DB/DbManager.cs b/Software/Visual_Studio/Tango.Core/DB/DbManager.cs index 1d415fdb1..8601d67a0 100644 --- a/Software/Visual_Studio/Tango.Core/DB/DbManager.cs +++ b/Software/Visual_Studio/Tango.Core/DB/DbManager.cs @@ -65,9 +65,15 @@ namespace Tango.Core.DB #region Public Methods - public void Create(String name) + public void Create(String name, String filePath = null) { String command = String.Format("CREATE DATABASE {0}", name); + + if (filePath != null) + { + command = $"CREATE DATABASE {name} ON (name='{name}', filename='{filePath}')"; + } + SqlCommand cmd = new SqlCommand(command, _connection); cmd.ExecuteNonQuery(); } @@ -160,6 +166,13 @@ namespace Tango.Core.DB SetOnline(name); } + public void RestoreAsNew(String name, String file, String dbFolder) + { + String command = $"RESTORE DATABASE {name} FROM DISK='{file}' WITH MOVE '{name}' TO '{Path.Combine(dbFolder, name)}.mdf', MOVE '{name}_log' TO '{Path.Combine(dbFolder, name)}.ldf'"; + SqlCommand cmd = new SqlCommand(command, _connection); + cmd.ExecuteNonQuery(); + } + public void ClearDb() { if (!_connection.ConnectionString.ToLower().Contains("initial catalog")) @@ -265,6 +278,24 @@ EXEC sp_executesql @statement return cred; } + public String GetValue(String query, String columnName) + { + string sql = query; + var cm = new SqlCommand(sql, _connection); + var dr = cm.ExecuteReader(); + if (dr.Read()) + { + var value = dr[columnName]; + + if (value != null) + { + return value.ToString(); + } + } + + return null; + } + #endregion #region IDisposable diff --git a/Software/Visual_Studio/Tango.PMR/FirmwareUpgrade/VersionFileDescriptor.cs b/Software/Visual_Studio/Tango.PMR/FirmwareUpgrade/VersionFileDescriptor.cs index 98a6c2efc..96b0a8525 100644 --- a/Software/Visual_Studio/Tango.PMR/FirmwareUpgrade/VersionFileDescriptor.cs +++ b/Software/Visual_Studio/Tango.PMR/FirmwareUpgrade/VersionFileDescriptor.cs @@ -23,16 +23,15 @@ namespace Tango.PMR.FirmwareUpgrade { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChtWZXJzaW9uRmlsZURlc2NyaXB0b3IucHJvdG8SGVRhbmdvLlBNUi5GaXJt", - "d2FyZVVwZ3JhZGUaHFZlcnNpb25GaWxlRGVzdGluYXRpb24ucHJvdG8ilAEK", + "d2FyZVVwZ3JhZGUaHFZlcnNpb25GaWxlRGVzdGluYXRpb24ucHJvdG8iggEK", "FVZlcnNpb25GaWxlRGVzY3JpcHRvchIQCghGaWxlTmFtZRgBIAEoCRIPCgdW", "ZXJzaW9uGAIgASgJEkYKC0Rlc3RpbmF0aW9uGAMgASgOMjEuVGFuZ28uUE1S", - "LkZpcm13YXJlVXBncmFkZS5WZXJzaW9uRmlsZURlc3RpbmF0aW9uEhAKCENo", - "ZWNrU3VtGAQgASgMQiUKI2NvbS50d2luZS50YW5nby5wbXIuZmlybXdhcmV1", - "cGdyYWRlYgZwcm90bzM=")); + "LkZpcm13YXJlVXBncmFkZS5WZXJzaW9uRmlsZURlc3RpbmF0aW9uQiUKI2Nv", + "bS50d2luZS50YW5nby5wbXIuZmlybXdhcmV1cGdyYWRlYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Tango.PMR.FirmwareUpgrade.VersionFileDestinationReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.FirmwareUpgrade.VersionFileDescriptor), global::Tango.PMR.FirmwareUpgrade.VersionFileDescriptor.Parser, new[]{ "FileName", "Version", "Destination", "CheckSum" }, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.FirmwareUpgrade.VersionFileDescriptor), global::Tango.PMR.FirmwareUpgrade.VersionFileDescriptor.Parser, new[]{ "FileName", "Version", "Destination" }, null, null, null) })); } #endregion @@ -66,7 +65,6 @@ namespace Tango.PMR.FirmwareUpgrade { fileName_ = other.fileName_; version_ = other.version_; destination_ = other.destination_; - checkSum_ = other.checkSum_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -107,17 +105,6 @@ namespace Tango.PMR.FirmwareUpgrade { } } - /// Field number for the "CheckSum" field. - public const int CheckSumFieldNumber = 4; - private pb::ByteString checkSum_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pb::ByteString CheckSum { - get { return checkSum_; } - set { - checkSum_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as VersionFileDescriptor); @@ -134,7 +121,6 @@ namespace Tango.PMR.FirmwareUpgrade { if (FileName != other.FileName) return false; if (Version != other.Version) return false; if (Destination != other.Destination) return false; - if (CheckSum != other.CheckSum) return false; return true; } @@ -144,7 +130,6 @@ namespace Tango.PMR.FirmwareUpgrade { if (FileName.Length != 0) hash ^= FileName.GetHashCode(); if (Version.Length != 0) hash ^= Version.GetHashCode(); if (Destination != 0) hash ^= Destination.GetHashCode(); - if (CheckSum.Length != 0) hash ^= CheckSum.GetHashCode(); return hash; } @@ -167,10 +152,6 @@ namespace Tango.PMR.FirmwareUpgrade { output.WriteRawTag(24); output.WriteEnum((int) Destination); } - if (CheckSum.Length != 0) { - output.WriteRawTag(34); - output.WriteBytes(CheckSum); - } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -185,9 +166,6 @@ namespace Tango.PMR.FirmwareUpgrade { if (Destination != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Destination); } - if (CheckSum.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(CheckSum); - } return size; } @@ -205,9 +183,6 @@ namespace Tango.PMR.FirmwareUpgrade { if (other.Destination != 0) { Destination = other.Destination; } - if (other.CheckSum.Length != 0) { - CheckSum = other.CheckSum; - } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -230,10 +205,6 @@ namespace Tango.PMR.FirmwareUpgrade { destination_ = (global::Tango.PMR.FirmwareUpgrade.VersionFileDestination) input.ReadEnum(); break; } - case 34: { - CheckSum = input.ReadBytes(); - break; - } } } } diff --git a/Software/Visual_Studio/Tango.SQLExaminer/ExaminerSequenceConfigurationRunner.cs b/Software/Visual_Studio/Tango.SQLExaminer/ExaminerSequenceConfigurationRunner.cs index de146ead3..b9ee0cf7a 100644 --- a/Software/Visual_Studio/Tango.SQLExaminer/ExaminerSequenceConfigurationRunner.cs +++ b/Software/Visual_Studio/Tango.SQLExaminer/ExaminerSequenceConfigurationRunner.cs @@ -24,6 +24,15 @@ namespace Tango.SQLExaminer public ExaminerSequenceConfiguration Configuration { get; private set; } + public ExaminerSequenceConfigurationRunner(ExaminerSequenceConfiguration sequenceConfiguration, String scriptsFolder, Core.DataSource source, Core.DataSource target, String machineSerialNumber) + { + ScriptsFolder = scriptsFolder; + Source = source; + Target = target; + MachineSerialNumber = machineSerialNumber; + Configuration = sequenceConfiguration; + } + public ExaminerSequenceConfigurationRunner(String sequenceFile, String scriptsFolder, Core.DataSource source, Core.DataSource target, String machineSerialNumber) { SequenceFile = sequenceFile; diff --git a/Software/Visual_Studio/Tango.SQLExaminer/ExtensionMethods.cs b/Software/Visual_Studio/Tango.SQLExaminer/ExtensionMethods.cs new file mode 100644 index 000000000..09a830ab3 --- /dev/null +++ b/Software/Visual_Studio/Tango.SQLExaminer/ExtensionMethods.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.SQLExaminer; + +public static class ExtensionMethods +{ + public static String GetFilePath(this ExaminerConfigurationType type) + { + return Path.Combine(Helper.SQL_EXAMINER_CONFIG_FOLDER, type.ToString() + ".xml"); + } + + public static String GetFileName(this ExaminerConfigurationType type) + { + return type.ToString() + ".xml"; + } +} + diff --git a/Software/Visual_Studio/Tango.SQLExaminer/Helper.cs b/Software/Visual_Studio/Tango.SQLExaminer/Helper.cs index 5eb09b98c..3b4e238a7 100644 --- a/Software/Visual_Studio/Tango.SQLExaminer/Helper.cs +++ b/Software/Visual_Studio/Tango.SQLExaminer/Helper.cs @@ -8,7 +8,7 @@ using Tango.Core.Helpers; namespace Tango.SQLExaminer { - internal static class Helper + public static class Helper { public static String SQL_EXAMINER_FOLDER = Path.Combine(AssemblyHelper.GetCurrentAssemblyFolder(), "SQLExaminer"); public static String SQL_EXAMINER_CONFIG_FOLDER = Path.Combine(SQL_EXAMINER_FOLDER, "Configurations"); diff --git a/Software/Visual_Studio/Tango.SQLExaminer/Tango.SQLExaminer.csproj b/Software/Visual_Studio/Tango.SQLExaminer/Tango.SQLExaminer.csproj index b71a30dc0..17dcb1b22 100644 --- a/Software/Visual_Studio/Tango.SQLExaminer/Tango.SQLExaminer.csproj +++ b/Software/Visual_Studio/Tango.SQLExaminer/Tango.SQLExaminer.csproj @@ -69,6 +69,7 @@ + diff --git a/Software/Visual_Studio/Tango.UnitTesting/SQLExaminer/SQLExaminer_TST.cs b/Software/Visual_Studio/Tango.UnitTesting/SQLExaminer/SQLExaminer_TST.cs index 9b0385c23..e3e49ac5e 100644 --- a/Software/Visual_Studio/Tango.UnitTesting/SQLExaminer/SQLExaminer_TST.cs +++ b/Software/Visual_Studio/Tango.UnitTesting/SQLExaminer/SQLExaminer_TST.cs @@ -391,5 +391,76 @@ namespace Tango.UnitTesting.SQLExaminer //Should have no differences! Assert.IsFalse(data_report.HasDifferences); } + + [TestMethod] + public void Perform_Machine_Update_From_Backup() + { + String tempDbName = "Tango_TUP"; + + var source_db = GetSource("Tango"); + var target_db = GetSource(tempDbName); + + DbManager dbManager = DbManager.FromDataSource(source_db); + + //Create the backup for the tup file. + dbManager.Create(tempDbName); + + var configuration = GetFullConfiguration(); + + ExaminerSequenceConfigurationRunner runner = + new ExaminerSequenceConfigurationRunner( + configuration, + Tango.SQLExaminer.Helper.SQL_EXAMINER_CONFIG_FOLDER, + source_db, + target_db, + "1111"); + + runner.Run().GetAwaiter().GetResult(); + + String backupFile = "C:\\DB_Backups\\Tango_TEMP.bak"; + + dbManager.Backup(tempDbName, backupFile); + dbManager.SetOffline(tempDbName); + dbManager.SetOnline(tempDbName); + dbManager.Delete(tempDbName); + + //Now restore as different name + dbManager.RestoreAsNew(tempDbName, backupFile, "C:\\DB_Backups"); + } + + private ExaminerSequenceConfiguration GetFullConfiguration() + { + ExaminerSequenceConfiguration configuration = new ExaminerSequenceConfiguration(); + + configuration.Items.Add(new ExaminerSequenceItem() + { + Type = ExaminerSequenceItemType.Schema, + Direction = ExaminerSequenceItemDirection.SourceToTarget, + FileName = ExaminerConfigurationType.Schema.GetFileName(), + Index = 0, + Name = "Updating Schema", + }); + + configuration.Items.Add(new ExaminerSequenceItem() + { + Type = ExaminerSequenceItemType.Data, + Direction = ExaminerSequenceItemDirection.SourceToTarget, + FileName = ExaminerConfigurationType.OverrideData.GetFileName(), + Index = 1, + Name = "Updating Collections", + }); + + configuration.Items.Add(new ExaminerSequenceItem() + { + Type = ExaminerSequenceItemType.Data, + Direction = ExaminerSequenceItemDirection.SourceToTarget, + FileName = ExaminerConfigurationType.ProvisionMachine.GetFileName(), + Index = 2, + Name = "Configuring Machine", + RequiresSerialNumber = true, + }); + + return configuration; + } } } diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs index 2eeaa6e0e..378fc3eea 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs @@ -23,6 +23,10 @@ using Tango.Web.ActiveDirectory; using Tango.MachineService.Filters; using Tango.MachineService.Security; using Tango.Web.SQLServer; +using Tango.Core; +using Tango.Web.SMO; +using Tango.Core.DB; +using System.Threading.Tasks; namespace Tango.MachineService.Controllers { @@ -425,6 +429,67 @@ namespace Tango.MachineService.Controllers }; } + [HttpPost] + [JwtTokenFilter] + public DownloadLatestPPCVersionResponse DownloadLatestPPCVersion(DownloadLatestPPCVersionRequest request) + { + DownloadLatestPPCVersionResponse response = new DownloadLatestPPCVersionResponse(); + + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == request.SerialNumber); + + if (machine == null) + { + throw new AuthenticationException("The specified serial number could not be found."); + } + + var machine_version = db.MachineVersions.SingleOrDefault(x => x.Guid == machine.MachineVersionGuid); + + var latest_machine_version = db.TangoVersions.Where(x => x.MachineVersionGuid == machine_version.Guid).ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); + + response.Version = latest_machine_version.Version; + + var manager = new BlobStorageManager(); + var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER); + var blob = container.GetBlockBlobReference(latest_machine_version.BlobName); + + response.BlobAddress = blob.GenerateReadSignature(TimeSpan.FromMinutes(60)); + + if (!String.IsNullOrWhiteSpace(MachineServiceConfig.CDN_ENDPOINT)) + { + response.CdnAddress = MachineServiceConfig.CDN_ENDPOINT + blob.Uri.AbsolutePath; + } + + DbCredentials credentials = new DbCredentials(); + + using (SmoManager smo = new SmoManager()) + { + credentials = smo.CreateRandomLoginAndUser(); + + Task.Delay(TimeSpan.FromMinutes(PPCController.SQL_TEMP_CREDENTIALS_EXP_MINUTS)).ContinueWith((x) => + { + using (SmoManager m = new SmoManager()) + { + m.DeleteLoginAndUser(credentials.UserName); + } + }); + } + + response.DataSource = new DataSource() + { + Address = MachineServiceConfig.DB_ADDRESS, + Catalog = MachineServiceConfig.DB_CATALOG, + UserName = credentials.UserName, + Password = credentials.Password, + IntegratedSecurity = false, + Type = DataSourceType.SQLServer, + }; + } + + return response; + } + #endregion } } diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs index 2dee09e69..0d9a2993b 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs @@ -32,7 +32,7 @@ namespace Tango.MachineService.Controllers private static List _pendingUploads; private static List _pendingUpdates; private ActiveDirectoryManager _ad_manager; - private const int SQL_TEMP_CREDENTIALS_EXP_MINUTS = 20; + public const int SQL_TEMP_CREDENTIALS_EXP_MINUTS = 20; public class TokenObject { -- cgit v1.3.1 From d5827e26ff5ee1b0532530bce4da3533f71a63dd Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Mon, 9 Dec 2019 20:07:12 +0200 Subject: Added LocalDB to machine prerequisit to machine studio installer. Implemented machine studio installer feature selection. Removed roslyn folder from MS release output. Added date to tup file generation. Added LocalDB start before connect service on TupFileBuilder. --- .../Machine Studio Installer.aip | 1412 +++++++++++++------- .../ViewModels/TupViewVM.cs | 2 +- .../Tup/TupFileBuilder.cs | 5 +- .../Tango.MachineStudio.UI.csproj | 3 +- 4 files changed, 914 insertions(+), 508 deletions(-) (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/Visual_Studio/Advanced Installer Projects/Machine Studio Installer.aip b/Software/Visual_Studio/Advanced Installer Projects/Machine Studio Installer.aip index b29828743..bfc3229b5 100644 --- a/Software/Visual_Studio/Advanced Installer Projects/Machine Studio Installer.aip +++ b/Software/Visual_Studio/Advanced Installer Projects/Machine Studio Installer.aip @@ -1,5 +1,5 @@ - + @@ -11,6 +11,7 @@ + @@ -36,11 +37,13 @@ + + + - @@ -49,26 +52,30 @@ + - + + - + - - + + + - - + + + @@ -76,10 +83,10 @@ - + - - + + @@ -89,34 +96,46 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - + + + + - + + + + + + + + + + - - + + + + @@ -129,8 +148,8 @@ - - + + @@ -157,7 +176,7 @@ - + @@ -179,7 +198,7 @@ - + @@ -205,7 +224,7 @@ - + @@ -219,7 +238,7 @@ - + @@ -228,76 +247,83 @@ - + - - - - - - - - + + + + + + + + - + - - - + + + - + - - - + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - + + + + + + + + - - + + + - + - - + + - + - + @@ -306,9 +332,9 @@ - + - + @@ -333,429 +359,448 @@ - - - - + + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -772,6 +817,7 @@ + @@ -793,8 +839,13 @@ + + + + + @@ -808,10 +859,23 @@ + + + + + + + + + + + + + - + - + @@ -834,10 +898,15 @@ + + + + + - + @@ -847,6 +916,7 @@ + @@ -855,14 +925,18 @@ + + + + @@ -870,17 +944,336 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -899,6 +1292,7 @@ + @@ -910,6 +1304,11 @@ + + + + + @@ -927,6 +1326,7 @@ + @@ -934,8 +1334,8 @@ - - + + @@ -947,13 +1347,15 @@ - + + + - + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/TupViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/TupViewVM.cs index 12ed09c75..5d1703dc3 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/TupViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/TupViewVM.cs @@ -88,7 +88,7 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels dlg.Title = "Select package location"; dlg.Filter = "Tango Update Package Files|*.tup"; dlg.DefaultExt = ".tup"; - dlg.FileName = LatestVersion == null ? $"{Machine.SerialNumber}_Update.tup" : $"{Machine.SerialNumber}_Update_v{LatestVersion}.tup"; + dlg.FileName = LatestVersion == null ? $"{Machine.SerialNumber}_Update_{DateTime.Now.Date.ToFileName()}.tup" : $"{Machine.SerialNumber}_Update_{DateTime.Now.Date.ToFileName()}_v{LatestVersion}.tup"; if (dlg.ShowDialog().Value) { diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilder.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilder.cs index 6dd8b82f7..fad6ce949 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilder.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilder.cs @@ -69,9 +69,12 @@ namespace Tango.MachineStudio.Common.Tup { LogManager.Log(ex, "Could not connect using SQLEXPRESS. Trying local DB..."); - CmdCommand command = new CmdCommand("sqllocaldb", "info \"MSSQLLocalDB\""); + CmdCommand command = new CmdCommand("sqllocaldb", "start \"MSSQLLocalDB\""); var result = command.Run().Result; + command = new CmdCommand("sqllocaldb", "info \"MSSQLLocalDB\""); + result = command.Run().Result; + String pattern = "np:.+"; Regex reg = new Regex(pattern); var match = reg.Match(result.StandardOutput); diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index c6cf624b3..470cfe4c7 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -654,7 +654,8 @@ copy /Y "$(SolutionDir)Referenced Assemblies\vcruntime140d.dll" "$(TargetDir)" copy /Y "$(SolutionDir)Referenced Assemblies\Microsoft.WITDataStore32.dll" "$(TargetDir)" if $(ConfigurationName) == Release del *.xml -if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)ProtoCompilers\" +if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)ProtoCompilers\" +if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)Roslyn\" -- cgit v1.3.1 From 3f069bb4a5303b2c732ba1263229f62526acc693 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Tue, 10 Dec 2019 00:39:06 +0200 Subject: Refactored Object mapping extension methods ! Removed FK from JOB_RUNS => JOBS Added MACHINE_GUID to JOB_RUNS Refactored MS Statistics module for the new changes. --- Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 22675456 -> 22675456 bytes .../ViewModels/MainViewVM.cs | 2 +- .../ViewModels/MainViewVM.cs | 2 +- .../Models/JobRunModel.cs | 45 +++++++ .../Tango.MachineStudio.Statistics.csproj | 1 + .../ViewModels/MainViewVM.cs | 23 ++-- .../ViewModels/ConnectedMachineViewVM.cs | 6 +- .../ViewModels/MainViewVM.cs | 2 +- .../Tango.BL/Builders/JobRunsBuilder.cs | 12 -- .../Visual_Studio/Tango.BL/DTO/JobRunDTOBase.cs | 8 ++ Software/Visual_Studio/Tango.BL/Entities/Job.cs | 4 +- .../Visual_Studio/Tango.BL/Entities/JobBase.cs | 38 ------ .../Visual_Studio/Tango.BL/Entities/JobRunBase.cs | 67 ++++------ .../ExtensionMethods/ObjectExtensions.cs | 113 ++++++++-------- Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs | 3 - .../Visual_Studio/Tango.DAL.Remote/DB/JOB_RUNS.cs | 3 +- .../Tango.DAL.Remote/DB/RemoteADO.Designer.cs | 2 +- .../Tango.DAL.Remote/DB/RemoteADO.edmx | 61 +++------ .../Tango.DAL.Remote/DB/RemoteADO.edmx.diagram | 147 ++++++++++----------- .../JobRuns/BasicJobRunsLogger.cs | 3 + .../Remote/RemoteDBComparer.cs | 4 +- Software/Visual_Studio/Tango.sln | 13 +- .../Utilities/Tango.JobRunsGenerator/Program.cs | 81 +++--------- 24 files changed, 278 insertions(+), 362 deletions(-) create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index f50c8b7fb..0336edc76 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 5b78ee141..dd9945ab8 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/ViewModels/MainViewVM.cs index 256ed24d6..9a80eb9d9 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/ViewModels/MainViewVM.cs @@ -221,7 +221,7 @@ namespace Tango.MachineStudio.HardwareDesigner.ViewModels private void CopyParameters(object obj) { - obj.MapPrimitivesTo(SelectedHardwareObject, + obj.MapPropertiesTo(SelectedHardwareObject, MappingFlags.PrimitivesOnly, (prop) => !prop.PropertyType.IsEnum && diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs index ee21b9ac3..9939e4876 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs @@ -471,7 +471,7 @@ namespace Tango.MachineStudio.RML.ViewModels var rml = await new RmlBuilder(context).Set(SelectedRML.Guid).WithActiveParametersGroup().WithLiquidFactors().BuildAsync(); Rml cloned = new Rml(); - rml.MapPrimitivesWithStrings(cloned); + rml.MapPropertiesTo(cloned, MappingFlags.NoReferenceTypes); cloned.Code = Rmls.Max(x => x.Code) + 1; cloned.Guid = Guid.NewGuid().ToString(); diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs new file mode 100644 index 000000000..8e5642e3d --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs @@ -0,0 +1,45 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL; +using Tango.BL.Entities; +using Tango.Core.ExtensionMethods; + +namespace Tango.MachineStudio.Statistics.Models +{ + public class JobRunModel : JobRun + { + private static Dictionary _machines = new Dictionary(); + + public JobRunModel() + { + + } + + public JobRunModel(JobRun run) + { + run.MapPropertiesTo(this, MappingFlags.NoReferenceTypes); + } + + public Task LoadMachine(ObservablesContext context) + { + return Task.Factory.StartNew(() => + { + if (!_machines.ContainsKey(MachineGuid)) + { + Machine = context.Machines.SingleOrDefault(x => x.Guid == MachineGuid); + _machines.Add(MachineGuid, Machine); + } + else + { + Machine = _machines[MachineGuid]; + } + }); + } + + public Machine Machine { get; set; } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj index 243663c5a..36c371165 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj @@ -73,6 +73,7 @@ + PieChartTooltipControl.xaml diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs index ef9561d0b..dfbfe2648 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs @@ -7,20 +7,20 @@ using System.Text; using System.Threading.Tasks; using System.Windows.Media; using Tango.BL; -using Tango.BL.Entities; using Tango.BL.Enumerations; using Tango.Core.Helpers; using Tango.MachineStudio.Common; using Tango.MachineStudio.Statistics.Models; using System.Data.Entity; using Tango.MachineStudio.Common.Notifications; +using Tango.BL.Entities; namespace Tango.MachineStudio.Statistics.ViewModels { public class MainViewVM : StudioViewModel { private ObservablesContext _context; - private List _job_runs; + private List _job_runs; private bool rendered; private INotificationProvider _notification; private bool _loaded; @@ -74,7 +74,6 @@ namespace Tango.MachineStudio.Statistics.ViewModels set { _maxDate = value; RaisePropertyChangedAuto(); } } - public MainViewVM(INotificationProvider notificationProvider) { _notification = notificationProvider; @@ -88,12 +87,12 @@ namespace Tango.MachineStudio.Statistics.ViewModels } - private List GetJobRunsByDateRange(DateTime startDate, DateTime endTime, JobRunStatus? status = null) + private List GetJobRunsByDateRange(DateTime startDate, DateTime endTime, JobRunStatus? status = null) { return _job_runs.Where(x => x.StartDate.ToLocalTime() >= startDate && x.StartDate.ToLocalTime() <= endTime && (status == null || x.JobRunStatus == status)).ToList(); } - private List GetJobRunsByDate(DateTime date, JobRunStatus? status = null) + private List GetJobRunsByDate(DateTime date, JobRunStatus? status = null) { return _job_runs.Where(x => x.StartDate.ToLocalTime().Date == date.Date && (status == null || x.JobRunStatus == status)).ToList(); } @@ -106,8 +105,6 @@ namespace Tango.MachineStudio.Statistics.ViewModels } } - - public override async void OnNavigatedTo() { base.OnNavigatedTo(); @@ -124,7 +121,11 @@ namespace Tango.MachineStudio.Statistics.ViewModels await Task.Factory.StartNew(() => { _context = ObservablesContext.CreateDefault(); - _job_runs = _context.JobRuns.Include(x => x.Job).Include(x => x.Job.Machine).OrderBy(x => x.StartDate).ToList(); + _job_runs = _context.JobRuns.OrderBy(x => x.StartDate).ToList().Select(x => new JobRunModel(x)).ToList(); + foreach (var run in _job_runs) + { + run.LoadMachine(_context).GetAwaiter().GetResult(); + } }); if (_job_runs.Count > 0) @@ -282,12 +283,12 @@ namespace Tango.MachineStudio.Statistics.ViewModels private void GeneratePrintPerWeekChart() { - List range_job_runs = GetJobRunsByDateRange(StartDate, EndDate); + List range_job_runs = GetJobRunsByDateRange(StartDate, EndDate); Dictionary> weeks_print_avg = new Dictionary>(); //Init machines weeks averages dictionary. - foreach (var machine in range_job_runs.Select(x => x.Job.Machine).OrderBy(x => x.Name).DistinctBy(x => x.Guid)) + foreach (var machine in range_job_runs.Select(x => x.Machine).OrderBy(x => x.Name).DistinctBy(x => x.Guid)) { weeks_print_avg[machine] = new List(); } @@ -305,7 +306,7 @@ namespace Tango.MachineStudio.Statistics.ViewModels { var week_job_runs = range_job_runs.Where(x => x.EndPosition > 10 && x.StartDate >= current_sunday && x.StartDate <= current_sunday.AddDays(7)).ToList(); - foreach (var machine_job_runs in week_job_runs.GroupBy(x => x.Job.Machine)) + foreach (var machine_job_runs in week_job_runs.GroupBy(x => x.Machine)) { weeks_print_avg[machine_job_runs.Key].Add(machine_job_runs.Select(x => x.EndPosition).Average()); } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ConnectedMachineViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ConnectedMachineViewVM.cs index 16f6938a0..40479895d 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ConnectedMachineViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ConnectedMachineViewVM.cs @@ -95,11 +95,11 @@ namespace Tango.MachineStudio.UI.ViewModels using (ObservablesContext db = ObservablesContext.CreateDefault()) { - var jobs = await db.Jobs.Include(x => x.JobRuns).Where(x => x.MachineGuid == ApplicationManager.Machine.Guid).ToListAsync(); + var jobRuns = await db.JobRuns.Where(x => x.MachineGuid == ApplicationManager.Machine.Guid).ToListAsync(); - TotalMachineWorkTime = TimeSpan.FromHours(jobs.SelectMany(x => x.JobRuns).Select(x => x.EndDate - x.StartDate).Sum(x => x.TotalHours)).ToString(@"hh\:mm\:ss"); + TotalMachineWorkTime = TimeSpan.FromHours(jobRuns.Select(x => x.EndDate - x.StartDate).Sum(x => x.TotalHours)).ToString(@"hh\:mm\:ss"); - int meters = (int)jobs.SelectMany(x => x.JobRuns).Select(x => x.EndPosition).Sum(); + int meters = (int)jobRuns.Select(x => x.EndPosition).Sum(); TotalMachineMeters = $"{meters.ToString("N0")} meters"; } } diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs index 598b1a194..3cceba6c9 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs @@ -155,7 +155,7 @@ namespace Tango.PPC.MachineSettings.ViewModels { Settings.SupportedJobTypes = SelectedJobTypes.SynchedSource.ToList(); Settings.SupportedColorSpaces = SelectedColorSpaces.SynchedSource.ToList(); - Machine.MapPrimitivesWithStrings(MachineProvider.Machine); + Machine.MapPropertiesTo(MachineProvider.Machine, MappingFlags.NoReferenceTypes); Settings.EnableHotSpot = EnableHotSpot; Settings.HotSpotPassword = HotSpotPassword; diff --git a/Software/Visual_Studio/Tango.BL/Builders/JobRunsBuilder.cs b/Software/Visual_Studio/Tango.BL/Builders/JobRunsBuilder.cs index 0a02c6a23..ca755a04c 100644 --- a/Software/Visual_Studio/Tango.BL/Builders/JobRunsBuilder.cs +++ b/Software/Visual_Studio/Tango.BL/Builders/JobRunsBuilder.cs @@ -15,17 +15,5 @@ namespace Tango.BL.Builders } - protected override IQueryable OnSetQuery(IQueryable query) - { - return query.Include(x => x.Job); - } - - public virtual JobRunsBuilder WithJobEvents() - { - return AddStep(2, () => - { - Context.MachinesEvents.Where(x => x.MachineGuid == Entity.Job.MachineGuid && x.DateTime >= Entity.StartDate && x.DateTime <= Entity.EndDate).OrderBy(x => x.DateTime).ToList(); - }); - } } } diff --git a/Software/Visual_Studio/Tango.BL/DTO/JobRunDTOBase.cs b/Software/Visual_Studio/Tango.BL/DTO/JobRunDTOBase.cs index 112694e1a..9726f16a7 100644 --- a/Software/Visual_Studio/Tango.BL/DTO/JobRunDTOBase.cs +++ b/Software/Visual_Studio/Tango.BL/DTO/JobRunDTOBase.cs @@ -26,6 +26,14 @@ namespace Tango.BL.DTO public abstract class JobRunDTOBase : ObservableEntityDTO { + /// + /// machine guid + /// + public String MachineGuid + { + get; set; + } + /// /// job guid /// diff --git a/Software/Visual_Studio/Tango.BL/Entities/Job.cs b/Software/Visual_Studio/Tango.BL/Entities/Job.cs index 3cb6494d4..19f374951 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/Job.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/Job.cs @@ -628,7 +628,7 @@ namespace Tango.BL.Entities foreach (var stop in segment.BrushStops.OrderBy(x => x.StopIndex)) { JobFileBrushStop st = new JobFileBrushStop(); - stop.MapPrimitivesWithStringsNoNullsTo(st); + stop.MapPropertiesTo(st, MappingFlags.NoReferenceTypes | MappingFlags.NoNullStrings); st.ColorCatalogItemGuid = stop.ColorCatalogsItemGuid.ToStringOrEmpty(); foreach (var idsPack in machine.Configuration.NoneEmptyIdsPacks) @@ -755,7 +755,7 @@ namespace Tango.BL.Entities BrushStop st = new BrushStop(); st.StopIndex = j + 1; st.SegmentGuid = s.Guid; - stop.MapPrimitivesWithStringsNoNullsTo(st); + stop.MapPropertiesTo(st, MappingFlags.NoReferenceTypes | MappingFlags.NoNullStrings); foreach (var volume in stop.LiquidVolumes) { diff --git a/Software/Visual_Studio/Tango.BL/Entities/JobBase.cs b/Software/Visual_Studio/Tango.BL/Entities/JobBase.cs index c5354f2c7..b356ecbfe 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/JobBase.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/JobBase.cs @@ -87,8 +87,6 @@ namespace Tango.BL.Entities public event EventHandler CustomerChanged; - public event EventHandler> JobRunsChanged; - public event EventHandler MachineChanged; public event EventHandler RmlChanged; @@ -1091,31 +1089,6 @@ namespace Tango.BL.Entities } } - protected SynchronizedObservableCollection _jobruns; - - /// - /// Gets or sets the jobbase job runs. - /// - - public virtual SynchronizedObservableCollection JobRuns - { - get - { - return _jobruns; - } - - set - { - if (_jobruns != value) - { - _jobruns = value; - - OnJobRunsChanged(value); - - } - } - } - protected Machine _machine; /// @@ -1553,15 +1526,6 @@ namespace Tango.BL.Entities RaisePropertyChanged(nameof(Customer)); } - /// - /// Called when the JobRuns has changed. - /// - protected virtual void OnJobRunsChanged(SynchronizedObservableCollection jobruns) - { - JobRunsChanged?.Invoke(this, jobruns); - RaisePropertyChanged(nameof(JobRuns)); - } - /// /// Called when the Machine has changed. /// @@ -1622,8 +1586,6 @@ namespace Tango.BL.Entities public JobBase() : base() { - JobRuns = new SynchronizedObservableCollection(); - Segments = new SynchronizedObservableCollection(); } diff --git a/Software/Visual_Studio/Tango.BL/Entities/JobRunBase.cs b/Software/Visual_Studio/Tango.BL/Entities/JobRunBase.cs index 4d53a6d66..16351179f 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/JobRunBase.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/JobRunBase.cs @@ -41,7 +41,30 @@ namespace Tango.BL.Entities public event EventHandler FailedMessageChanged; - public event EventHandler JobChanged; + protected String _machineguid; + + /// + /// Gets or sets the jobrunbase machine guid. + /// + + [Column("MACHINE_GUID")] + + public String MachineGuid + { + get + { + return _machineguid; + } + + set + { + if (_machineguid != value) + { + _machineguid = value; + + } + } + } protected String _jobguid; @@ -50,7 +73,6 @@ namespace Tango.BL.Entities /// [Column("JOB_GUID")] - [ForeignKey("Job")] public String JobGuid { @@ -206,38 +228,6 @@ namespace Tango.BL.Entities } } - protected Job _job; - - /// - /// Gets or sets the jobrunbase job. - /// - - [XmlIgnore] - [JsonIgnore] - public virtual Job Job - { - get - { - return _job; - } - - set - { - if (_job != value) - { - _job = value; - - if (Job != null) - { - JobGuid = Job.Guid; - } - - OnJobChanged(value); - - } - } - } - /// /// Called when the StartDate has changed. /// @@ -283,15 +273,6 @@ namespace Tango.BL.Entities RaisePropertyChanged(nameof(FailedMessage)); } - /// - /// Called when the Job has changed. - /// - protected virtual void OnJobChanged(Job job) - { - JobChanged?.Invoke(this, job); - RaisePropertyChanged(nameof(Job)); - } - /// /// Initializes a new instance of the class. /// diff --git a/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs index fe2c7ff9a..e8ef9addd 100644 --- a/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs +++ b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs @@ -12,6 +12,34 @@ using Tango.Serialization; namespace Tango.Core.ExtensionMethods { + public enum MappingFlags + { + /// + /// All properties will be mapped. + /// + All = 1, + + /// + /// Do not map string properties. + /// + NoStrings = 2, + + /// + /// Do not map string properties with value of null. + /// + NoNullStrings = 4, + + /// + /// Do not map reference types. + /// + NoReferenceTypes = 8, + + /// + /// Map only primitive values. + /// + PrimitivesOnly, + } + /// /// Contains extension methods. /// @@ -58,85 +86,62 @@ namespace Tango.Core.ExtensionMethods } /// - /// Maps the object properties values to the destination object. + /// Maps the object primitive properties values to the destination object. /// - /// The source. - /// The destination. - public static void MapPrimitivesTo(this object source, object destination) + /// The source object. + /// The destination object. + /// The mapping flags. + /// Optional condition. + public static void MapPropertiesTo(this object source, object destination, MappingFlags flags = MappingFlags.NoReferenceTypes, Func condition = null) { - foreach (var prop in source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.PropertyType.IsPrimitive)) + foreach (var prop in source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { - var desProp = destination.GetType().GetProperty(prop.Name, BindingFlags.Public | BindingFlags.Instance); + var propType = prop.PropertyType; + var value = prop.GetValue(source); - if (desProp != null && desProp.PropertyType.IsPrimitive && desProp.SetMethod != null) + if (condition != null) { - desProp.SetValue(destination, prop.GetValue(source)); + if (!condition(prop)) continue; } - } - } - /// - /// Maps the object properties values to the destination object including strings and without assigning null string values from the source. - /// - /// The source. - /// The destination. - public static void MapPrimitivesWithStringsNoNullsTo(this object source, object destination) - { - foreach (var prop in source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.PropertyType.IsPrimitive || x.PropertyType == typeof(String))) - { - var desProp = destination.GetType().GetProperty(prop.Name, BindingFlags.Public | BindingFlags.Instance); + if (!propType.IsPrimitive && flags.HasFlag(MappingFlags.PrimitivesOnly)) + { + continue; + } - if (desProp != null && (desProp.PropertyType.IsPrimitive || desProp.PropertyType == typeof(String)) && desProp.SetMethod != null) + if (propType == typeof(String) && flags.HasFlag(MappingFlags.NoStrings)) { - var value = prop.GetValue(source); + continue; + } - if (desProp.PropertyType != typeof(String) || !String.IsNullOrEmpty(value as String)) - { - desProp.SetValue(destination, value); - } + if (propType.IsClass && propType != typeof(String) && flags.HasFlag(MappingFlags.NoReferenceTypes)) + { + continue; + } + + if (flags.HasFlag(MappingFlags.NoNullStrings) && propType == typeof(String) && String.IsNullOrEmpty(value as String)) + { + continue; } - } - } - /// - /// Maps the object properties values to the destination object including strings and without assigning null string values from the source. - /// - /// The source. - /// The destination. - public static void MapPrimitivesWithStrings(this object source, object destination) - { - foreach (var prop in source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.PropertyType.IsPrimitive || x.PropertyType == typeof(String))) - { var desProp = destination.GetType().GetProperty(prop.Name, BindingFlags.Public | BindingFlags.Instance); - if (desProp != null && (desProp.PropertyType.IsPrimitive || desProp.PropertyType == typeof(String)) && desProp.SetMethod != null) + if (desProp != null && desProp.PropertyType == prop.PropertyType && desProp.SetMethod != null) { - var value = prop.GetValue(source); - desProp.SetValue(destination, value); } } } + /// - /// Maps the object properties values to the destination object. + /// Maps the object primitive properties values to the destination object. /// /// The source. /// The destination. - public static void MapPrimitivesTo(this object source, object destination, Func condition) + public static void MapPrimitivesTo(this object source, object destination) { - foreach (var prop in source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.PropertyType.IsPrimitive)) - { - var desProp = destination.GetType().GetProperty(prop.Name, BindingFlags.Public | BindingFlags.Instance); - - if (desProp != null && desProp.PropertyType.IsPrimitive && desProp.SetMethod != null) - { - if (condition(prop)) - { - desProp.SetValue(destination, prop.GetValue(source)); - } - } - } + source.MapPropertiesTo(destination, MappingFlags.PrimitivesOnly); } /// diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs index eb8c0a998..17ec544c0 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs @@ -17,7 +17,6 @@ namespace Tango.DAL.Remote.DB [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public JOB() { - this.JOB_RUNS = new HashSet(); this.SEGMENTS = new HashSet(); } @@ -61,8 +60,6 @@ namespace Tango.DAL.Remote.DB public virtual COLOR_CATALOGS COLOR_CATALOGS { get; set; } public virtual COLOR_SPACES COLOR_SPACES { get; set; } public virtual CUSTOMER CUSTOMER { get; set; } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] - public virtual ICollection JOB_RUNS { get; set; } public virtual MACHINE MACHINE { get; set; } public virtual RML RML { get; set; } public virtual SPOOL_TYPES SPOOL_TYPES { get; set; } diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB_RUNS.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB_RUNS.cs index fb591afa0..24f61f03c 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB_RUNS.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB_RUNS.cs @@ -17,13 +17,12 @@ namespace Tango.DAL.Remote.DB public int ID { get; set; } public string GUID { get; set; } public System.DateTime LAST_UPDATED { get; set; } + public string MACHINE_GUID { get; set; } public string JOB_GUID { get; set; } public System.DateTime START_DATE { get; set; } public System.DateTime END_DATE { get; set; } public int STATUS { get; set; } public double END_POSITION { get; set; } public string FAILED_MESSAGE { get; set; } - - public virtual JOB JOB { get; set; } } } diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Designer.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Designer.cs index 17bc2683d..d26e67908 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Designer.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Designer.cs @@ -1,4 +1,4 @@ -// T4 code generation is enabled for model 'D:\Development\Tango\Software\Visual_Studio\Tango.DAL.Remote\DB\RemoteADO.edmx'. +// T4 code generation is enabled for model 'C:\DATA\Development\Tango\Software\Visual_Studio\Tango.DAL.Remote\DB\RemoteADO.edmx'. // To enable legacy code generation, change the value of the 'Code Generation Strategy' designer // property to 'Legacy ObjectContext'. This property is available in the Properties Window when the model // is open in the designer. diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx index 8607b9f07..8c8b66a5c 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx @@ -586,7 +586,8 @@ - + + @@ -1614,20 +1615,6 @@ - - - - - - - - - - - - - - @@ -1679,7 +1666,9 @@ - + + + @@ -2077,7 +2066,9 @@ - + + + @@ -2402,10 +2393,6 @@ - - - - @@ -2863,10 +2850,6 @@ - - - - @@ -3658,13 +3641,13 @@ - + + - @@ -3709,7 +3692,6 @@ - @@ -4925,20 +4907,6 @@ - - - - - - - - - - - - - - @@ -4954,7 +4922,9 @@ - + + + @@ -5286,7 +5256,9 @@ - + + + @@ -5958,6 +5930,7 @@ + diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram index c0574cb9e..2feb68642 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram @@ -5,80 +5,80 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -130,7 +130,6 @@ - diff --git a/Software/Visual_Studio/Tango.Integration/JobRuns/BasicJobRunsLogger.cs b/Software/Visual_Studio/Tango.Integration/JobRuns/BasicJobRunsLogger.cs index bacae9324..9eb010ec2 100644 --- a/Software/Visual_Studio/Tango.Integration/JobRuns/BasicJobRunsLogger.cs +++ b/Software/Visual_Studio/Tango.Integration/JobRuns/BasicJobRunsLogger.cs @@ -117,6 +117,7 @@ namespace Tango.Integration.JobRuns StartDate = _start_date, EndDate = DateTime.UtcNow, JobGuid = _job.Guid, + MachineGuid = _job.MachineGuid, JobRunStatus = JobRunStatus.Failed, EndPosition = e.JobHandler.Status.Progress, FailedMessage = e.Exception.Message, @@ -161,6 +162,7 @@ namespace Tango.Integration.JobRuns StartDate = _start_date, EndDate = DateTime.UtcNow, JobGuid = _job.Guid, + MachineGuid = _job.MachineGuid, EndPosition = e.JobHandler.Status.Progress, JobRunStatus = JobRunStatus.Aborted, }); @@ -204,6 +206,7 @@ namespace Tango.Integration.JobRuns StartDate = _start_date, EndDate = DateTime.UtcNow, JobGuid = _job.Guid, + MachineGuid = _job.MachineGuid, EndPosition = e.JobHandler.Status.Progress, JobRunStatus = JobRunStatus.Completed, }); diff --git a/Software/Visual_Studio/Tango.Synchronization/Remote/RemoteDBComparer.cs b/Software/Visual_Studio/Tango.Synchronization/Remote/RemoteDBComparer.cs index aaf4706a3..7022d1ae3 100644 --- a/Software/Visual_Studio/Tango.Synchronization/Remote/RemoteDBComparer.cs +++ b/Software/Visual_Studio/Tango.Synchronization/Remote/RemoteDBComparer.cs @@ -143,7 +143,7 @@ namespace Tango.Synchronization.Remote var remote_jobs = remote_machines.SelectMany(x => x.JOBS).ToList(); OnProgress(LogManager.Log("Querying all remote job runs...")); - var remote_jobs_runs = remote_jobs.SelectMany(x => x.JOB_RUNS).ToList(); + //var remote_jobs_runs = remote_jobs.SelectMany(x => x.JOB_RUNS).ToList(); OnProgress(LogManager.Log("Querying all remote segments...")); var remote_segments = remote_jobs.SelectMany(x => x.SEGMENTS).ToList(); @@ -196,7 +196,7 @@ namespace Tango.Synchronization.Remote CompareCollections(remote_jobs, local_jobs, _remoteDB.JOBS, _localDB.JOBS); OnProgress(LogManager.Log("Comparing job runs")); - CompareCollections(remote_jobs_runs, local_job_runs, _remoteDB.JOB_RUNS, _localDB.JOB_RUNS); + //CompareCollections(remote_jobs_runs, local_job_runs, _remoteDB.JOB_RUNS, _localDB.JOB_RUNS); OnProgress(LogManager.Log("Comparing segments")); CompareCollections(remote_segments, local_segments, _remoteDB.SEGMENTS, _localDB.SEGMENTS); diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln index 5d601ae52..8dc160543 100644 --- a/Software/Visual_Studio/Tango.sln +++ b/Software/Visual_Studio/Tango.sln @@ -3841,6 +3841,7 @@ Global {4EDCF067-E377-42CB-A18C-8368CF484577}.AppVeyor|x86.ActiveCfg = Release|Any CPU {4EDCF067-E377-42CB-A18C-8368CF484577}.AppVeyor|x86.Build.0 = Release|Any CPU {4EDCF067-E377-42CB-A18C-8368CF484577}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4EDCF067-E377-42CB-A18C-8368CF484577}.Debug|Any CPU.Build.0 = Debug|Any CPU {4EDCF067-E377-42CB-A18C-8368CF484577}.Debug|ARM.ActiveCfg = Debug|Any CPU {4EDCF067-E377-42CB-A18C-8368CF484577}.Debug|ARM.Build.0 = Debug|Any CPU {4EDCF067-E377-42CB-A18C-8368CF484577}.Debug|ARM64.ActiveCfg = Debug|Any CPU @@ -5885,12 +5886,12 @@ Global {DA391B02-AE28-4EA1-A80F-D0F4C8029FFA} = {E728CBD9-1AF4-4814-A218-E4BD26E7EDEA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {7986F7F4-A86A-4994-B1B6-0988D7F057B6} - BuildVersion_BuildVersioningStyle = None.None.Increment.DeltaBaseYearDayOfYear - BuildVersion_UpdateAssemblyVersion = True - BuildVersion_UpdateFileVersion = False - BuildVersion_StartDate = 2000/1/1 - BuildVersion_AssemblyInfoFilename = Properties\AssemblyInfo.cs BuildVersion_UseGlobalSettings = False + BuildVersion_AssemblyInfoFilename = Properties\AssemblyInfo.cs + BuildVersion_StartDate = 2000/1/1 + BuildVersion_UpdateFileVersion = False + BuildVersion_UpdateAssemblyVersion = True + BuildVersion_BuildVersioningStyle = None.None.Increment.DeltaBaseYearDayOfYear + SolutionGuid = {7986F7F4-A86A-4994-B1B6-0988D7F057B6} EndGlobalSection EndGlobal diff --git a/Software/Visual_Studio/Utilities/Tango.JobRunsGenerator/Program.cs b/Software/Visual_Studio/Utilities/Tango.JobRunsGenerator/Program.cs index 6c3c62606..61e74957c 100644 --- a/Software/Visual_Studio/Utilities/Tango.JobRunsGenerator/Program.cs +++ b/Software/Visual_Studio/Utilities/Tango.JobRunsGenerator/Program.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Tango.BL; using Tango.BL.Builders; using Tango.BL.Entities; +using Tango.Core; namespace Tango.JobRunsGenerator { @@ -13,75 +14,27 @@ namespace Tango.JobRunsGenerator { static void Main(string[] args) { - Console.WriteLine("Job Runs Generator Started..."); - - DateTime now = DateTime.UtcNow; - DateTime yearago = DateTime.UtcNow.AddYears(-1); - Random rnd = new Random(); - List messages = new List() - { - "Timeout failure", - "Thread Break", - "Application Exception", - "Over Temperature", - "Communication Error" - }; - - int count = 0; - - using (ObservablesContext db = ObservablesContext.CreateDefault("localhost\\SQLEXPRESS")) + DataSource dataSource = new DataSource(); + dataSource.Catalog = "Tango_DEV"; + dataSource.Address = "twine.database.windows.net"; + dataSource.IntegratedSecurity = false; + dataSource.UserName = "Roy"; + dataSource.Password = "Aa123456"; + + using (ObservablesContext db = ObservablesContext.CreateDefault(dataSource)) { - var machines = db.Machines.ToList(); - - foreach (var machine in machines) + foreach (var run in db.JobRuns.OrderBy(x => x.JobGuid)) { - new MachineBuilder(db).Set(machine).WithJobs().Build(); - - foreach (var job in machine.Jobs) - { - using (ObservablesContext db2 = ObservablesContext.CreateDefault("localhost\\SQLEXPRESS")) - { - for (DateTime date = yearago; date < now; date = date.AddDays(1)) - { - Console.WriteLine($"Adding job runs for machine '{machine.SerialNumber}' job '{job.Name}' date {date.ToShortDateString()}..."); - - for (int i = 0; i < rnd.Next(0, 9); i++) - { - int status = rnd.Next(0, 3); - String message = messages[rnd.Next(0, messages.Count)]; - - db2.JobRuns.Add(new JobRun() - { - StartDate = date, - EndDate = date.AddMinutes(rnd.Next(10, 61)), - JobGuid = job.Guid, - EndPosition = job.Length / rnd.Next(1, 11), - Status = status, - FailedMessage = status == 2 ? message : null, - }); - - count++; - } - } - - db2.SaveChanges(); - } - } + var job = db.Jobs.SingleOrDefault(x => x.Guid == run.JobGuid); + Console.WriteLine($"Fixing job {job.Name}..."); + run.MachineGuid = job.MachineGuid; } - Console.WriteLine($"The generator is about to insert {count} job runs to the database are you sure? [Y/N]:"); - var key = Console.ReadKey().Key; + Console.WriteLine("Saving changed..."); + db.SaveChanges(); - if (key == ConsoleKey.Y) - { - Console.WriteLine("Saving changes to database..."); - Console.WriteLine("Done!"); - Console.ReadLine(); - } - else - { - return; - } + Console.WriteLine("Done!"); + Console.ReadLine(); } } } -- cgit v1.3.1 From 621230afe9d9040536b43241e63117c9bb34beaa Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Wed, 11 Dec 2019 20:57:30 +0200 Subject: Implemented Jobs, JobRuns & Machine Events Synchronization. Added synchronizations to Updates view on Machine Designer. Removed request response events logging from machine studio. Fixed issue with exception throwing from machine service. Implemented "New jobs synchronized" notification item to PPC. Added synchronization to PPC settings. Added Synchronization view to technician module. Implemented PPC Schema synchronizer utility. Added custom query support to EntityCollectionBuilder. Added synchronization status to TangoUpdate. Removed FK from Jobs and Job runs. --- Software/DB/PPC/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/PPC/Tango_log.ldf | Bin 53673984 -> 53673984 bytes Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 22675456 -> 22675456 bytes .../ViewModels/MainViewVM.cs | 1 + .../ViewModels/MachineUpdatesViewVM.cs | 48 +- .../Views/MachineUpdateDetailsDialog.xaml | 3 + .../Views/MachineUpdatesView.xaml | 22 +- .../EventLogging/DefaultEventLogger.cs | 6 +- .../Web/MachineStudioWebClientBase.cs | 9 + .../Tango.MachineStudio.UI/App.xaml.cs | 2 +- .../DefaultAuthenticationProvider.cs | 5 +- .../Tango.MachineStudio.UI/ViewModelLocator.cs | 14 +- .../PPC/Modules/Tango.PPC.Jobs/Images/sync-job.png | Bin 0 -> 6743 bytes .../PPC/Modules/Tango.PPC.Jobs/Images/sync.png | Bin 0 -> 4127 bytes .../NewSynchronizardJobsNotificationItem.cs | 32 ++ .../NewSynchronizardJobsNotificationItemView.xaml | 26 + ...ewSynchronizardJobsNotificationItemView.xaml.cs | 30 ++ .../Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj | 13 +- .../Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs | 1 + .../Tango.PPC.Jobs/ViewModels/JobsViewVM.cs | 25 +- .../ViewModels/MainViewVM.cs | 59 +++ .../Tango.PPC.MachineSettings/Views/MainView.xaml | 43 +- .../Modules/Tango.PPC.Technician/Images/sync.png | Bin 0 -> 4127 bytes .../Tango.PPC.Technician.csproj | 11 + .../Tango.PPC.Technician/ViewModelLocator.cs | 12 + .../ViewModels/SynchronizationViewVM.cs | 41 ++ .../ViewModels/SystemViewVM.cs | 6 +- .../Tango.PPC.Technician/Views/CatalogView.xaml | 20 +- .../Tango.PPC.Technician/Views/MainView.xaml | 1 + .../Views/SynchronizationView.xaml | 133 +++++ .../Views/SynchronizationView.xaml.cs | 28 ++ .../Application/IPPCApplicationManager.cs | 5 + .../Connection/DefaultMachineProvider.cs | 18 + .../MachineSetup/MachineSetupManager.cs | 12 +- .../MachineUpdate/MachineUpdateManager.cs | 2 + .../PPC/Tango.PPC.Common/PPCSettings.cs | 24 + .../PPC/Tango.PPC.Common/PPCViewModel.cs | 7 + .../DefaultMachineDataSynchronizer.cs | 554 +++++++++++++++++++++ .../Synchronization/IMachineDataSynchronizer.cs | 26 + .../SynchronizationEndedEventArgs.cs | 15 + .../Synchronization/SynchronizationState.cs | 23 + .../Synchronization/SynchronizationStatus.cs | 47 ++ .../SynchronizationStatusChangedEventArgs.cs | 13 + .../PPC/Tango.PPC.Common/Tango.PPC.Common.csproj | 15 +- .../Web/DownloadMachineDataRequest.cs | 22 + .../Web/DownloadMachineDataResponse.cs | 25 + .../NotifyMachineDataDownloadCompletedRequest.cs | 25 + .../NotifyMachineDataDownloadCompletedResponse.cs | 16 + .../PPC/Tango.PPC.Common/Web/PPCWebClient.cs | 5 + .../PPC/Tango.PPC.Common/Web/PPCWebClientBase.cs | 36 ++ .../Web/SynchronizationFailedEntity.cs | 14 + .../PPC/Tango.PPC.Common/Web/UpdateDBRequest.cs | 2 + .../Web/UploadMachineDataRequest.cs | 27 + .../Web/UploadMachineDataResponse.cs | 26 + .../Tango.PPC.SchemaSynchronizer.CLI/App.config | 6 + .../Tango.PPC.SchemaSynchronizer.CLI/Program.cs | 54 ++ .../Properties/AssemblyInfo.cs | 36 ++ .../Tango.PPC.SchemaSynchronizer.CLI.csproj | 63 +++ .../PPCApplication/DefaultPPCApplicationManager.cs | 21 +- .../PPC/Tango.PPC.UI/ViewModelLocator.cs | 14 +- .../Builders/EntityCollectionBuilderBase.cs | 38 ++ Software/Visual_Studio/Tango.BL/DTO/JobDTO.cs | 5 + Software/Visual_Studio/Tango.BL/DTO/JobDTOBase.cs | 8 + .../Visual_Studio/Tango.BL/DTO/JobRunDTOBase.cs | 8 + .../Tango.BL/DTO/MachinesEventDTOBase.cs | 8 + Software/Visual_Studio/Tango.BL/DTO/SegmentDTO.cs | 5 + Software/Visual_Studio/Tango.BL/Entities/Job.cs | 1 + .../Visual_Studio/Tango.BL/Entities/JobBase.cs | 38 ++ .../Visual_Studio/Tango.BL/Entities/JobRunBase.cs | 38 ++ .../Tango.BL/Entities/MachinesEventBase.cs | 38 ++ .../Visual_Studio/Tango.BL/Entities/TangoUpdate.cs | 22 +- .../Tango.BL/Enumerations/TangoUpdateStatuses.cs | 9 +- .../Visual_Studio/Tango.BL/IObservableEntity.cs | 5 + .../Visual_Studio/Tango.BL/ObservableEntity.cs | 12 + .../Tango.BL/ObservablesContextExtension.cs | 31 +- .../Templates/TangoWebClientCodeFile.cshtml | 9 + .../ExtensionMethods/ExceptionExtensions.cs | 17 + Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs | 1 + .../Visual_Studio/Tango.DAL.Remote/DB/JOB_RUNS.cs | 1 + .../Tango.DAL.Remote/DB/MACHINES_EVENTS.cs | 1 + .../Tango.DAL.Remote/DB/RemoteADO.edmx | 9 + .../Tango.DAL.Remote/DB/RemoteADO.edmx.diagram | 146 +++--- .../Tango.Settings/SettingsManager.cs | 1 - .../Tango.Transport/Web/WebTransportClient.cs | 7 + .../Tango.Web/Controllers/TangoController.cs | 2 +- Software/Visual_Studio/Tango.Web/TangoWebClient.cs | 28 +- Software/Visual_Studio/Tango.sln | 43 ++ .../Controllers/MachineStudioController.cs | 11 +- .../Controllers/PPCController.cs | 277 ++++++++++- .../Web/Tango.MachineService/Web.config | 7 +- 91 files changed, 2444 insertions(+), 126 deletions(-) create mode 100644 Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync-job.png create mode 100644 Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync.png create mode 100644 Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItem.cs create mode 100644 Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml create mode 100644 Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml.cs create mode 100644 Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/sync.png create mode 100644 Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SynchronizationViewVM.cs create mode 100644 Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml create mode 100644 Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/IMachineDataSynchronizer.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationEndedEventArgs.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationState.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatus.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatusChangedEventArgs.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataRequest.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataResponse.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedRequest.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedResponse.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Web/SynchronizationFailedEntity.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataRequest.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataResponse.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/App.config create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Program.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Properties/AssemblyInfo.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Tango.PPC.SchemaSynchronizer.CLI.csproj (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/DB/PPC/Tango.mdf b/Software/DB/PPC/Tango.mdf index 92884377a..41f7704e8 100644 Binary files a/Software/DB/PPC/Tango.mdf and b/Software/DB/PPC/Tango.mdf differ diff --git a/Software/DB/PPC/Tango_log.ldf b/Software/DB/PPC/Tango_log.ldf index 9a2dcca84..efb976613 100644 Binary files a/Software/DB/PPC/Tango_log.ldf and b/Software/DB/PPC/Tango_log.ldf differ diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index 0336edc76..596d62f57 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 dd9945ab8..ecf74c79f 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs index 63cfa10b8..46b4c301f 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs @@ -1914,6 +1914,7 @@ namespace Tango.MachineStudio.Developer.ViewModels { LogManager.Log(String.Format("Saving the active job {0}...", ActiveJob.Name)); ActiveJob.LastUpdated = DateTime.UtcNow; + ActiveJob.IsSynchronized = false; ActiveJob.Rml = SelectedRML; ActiveJob.EstimatedDurationMili = (int)EstimatedDuration.TotalMilliseconds; _activeJobDbContext.SaveChanges(); diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MachineUpdatesViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MachineUpdatesViewVM.cs index 7ff64c505..3ac3110bb 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MachineUpdatesViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MachineUpdatesViewVM.cs @@ -8,6 +8,7 @@ using System.Windows.Data; using Tango.BL; using Tango.BL.Builders; using Tango.BL.Entities; +using Tango.Core.Commands; using Tango.MachineStudio.Common.Notifications; using Tango.MachineStudio.MachineDesigner.Views; using Tango.SharedUI; @@ -17,6 +18,7 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels public class MachineUpdatesViewVM : ViewModel { private INotificationProvider _notification; + private ObservablesContext _context; #region Properties @@ -70,6 +72,19 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels set { _displayDatabaseUpdates = value; RaisePropertyChangedAuto(); OnFilterChanged(); } } + private bool _displaySynchronizations; + public bool DisplaySynchronizations + { + get { return _displaySynchronizations; } + set { _displaySynchronizations = value; RaisePropertyChangedAuto(); OnFilterChanged(); } + } + + #endregion + + #region Commands + + public RelayCommand RefreshCommand { get; set; } + #endregion #region Constructors @@ -79,6 +94,9 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels DisplayApplicationUpdates = true; DisplayMachineSetups = true; DisplayDatabaseUpdates = true; + DisplaySynchronizations = true; + + RefreshCommand = new RelayCommand(Refresh, () => IsFree); } public MachineUpdatesViewVM(INotificationProvider notificationProvider) : this() @@ -92,17 +110,36 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels public async Task Init(Machine machine, ObservablesContext context) { - Machine = machine; - Updates = (await new TangoUpdatesCollectionBuilder(context).Set(x => x.MachineGuid == machine.Guid).BuildAsync()).OrderByDescending(x => x.StartDate).ToList(); - UpdatesView = CollectionViewSource.GetDefaultView(Updates); - UpdatesView.Filter = UpdatesFilter; - OnFilterChanged(); + try + { + _context = context; + Machine = machine; + Updates = (await new TangoUpdatesCollectionBuilder(context).Set(x => x.MachineGuid == machine.Guid).BuildAsync()).OrderByDescending(x => x.StartDate).ToList(); + UpdatesView = CollectionViewSource.GetDefaultView(Updates); + UpdatesView.Filter = UpdatesFilter; + OnFilterChanged(); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error loading machine updates."); + _notification.ShowError($"An error occurred while loading the history of machine updates.\n{ex.FlattenMessage()}"); + } } #endregion #region Private Methods + private async void Refresh() + { + IsFree = false; + using (_notification.PushTaskItem("Refreshing machine updates...")) + { + await Init(Machine, _context); + } + IsFree = true; + } + private void OnFilterChanged() { if (UpdatesView != null) @@ -119,6 +156,7 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels if (!DisplayMachineSetups && update.IsSetup) return false; if (!DisplayApplicationUpdates && update.IsUpdate) return false; if (!DisplayDatabaseUpdates && update.IsDataBase) return false; + if (!DisplaySynchronizations && update.IsSynchronization) return false; return true; } else diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineUpdateDetailsDialog.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineUpdateDetailsDialog.xaml index 9d60d36f8..804ee456c 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineUpdateDetailsDialog.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineUpdateDetailsDialog.xaml @@ -40,6 +40,9 @@ + + + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineUpdatesView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineUpdatesView.xaml index d9ea2cb44..8d1ff8ec8 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineUpdatesView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineUpdatesView.xaml @@ -18,9 +18,9 @@ - + - + @@ -34,11 +34,16 @@ - - Machine Setups - Software Updates - Database Updates - + + + Machine Setups + Software Updates + Database Updates + Synchronizations + + + + @@ -66,6 +71,9 @@ + + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/EventLogging/DefaultEventLogger.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/EventLogging/DefaultEventLogger.cs index 11d156292..9992d4e2f 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/EventLogging/DefaultEventLogger.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/EventLogging/DefaultEventLogger.cs @@ -137,7 +137,7 @@ namespace Tango.MachineStudio.Common.EventLogging /// The message. private void Machine_RequestSent(object sender, IMessage message) { - Log(EventTypes.REQUEST_SENT, String.Format("Sending request '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString())); + //Log(EventTypes.REQUEST_SENT, String.Format("Sending request '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString())); } /// @@ -147,7 +147,7 @@ namespace Tango.MachineStudio.Common.EventLogging /// The instance containing the event data. private void Machine_RequestFailed(object sender, RequestFailedEventArgs e) { - Log(EventTypes.REQUEST_FAILED, String.Format("Request failed '{0}'...{1}{2}{1}{3}", e.Message.GetType().Name, Environment.NewLine, e.Message.ToJsonString(), e.Exception.ToString())); + //Log(EventTypes.REQUEST_FAILED, String.Format("Request failed '{0}'...{1}{2}{1}{3}", e.Message.GetType().Name, Environment.NewLine, e.Message.ToJsonString(), e.Exception.ToString())); } /// @@ -157,7 +157,7 @@ namespace Tango.MachineStudio.Common.EventLogging /// The message. private void Machine_ResponseReceived(object sender, IMessage message) { - Log(EventTypes.RESPONSE_RECEIVED, String.Format("Response received '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString())); + //Log(EventTypes.RESPONSE_RECEIVED, String.Format("Response received '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString())); } /// diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs index c2d0dd3e6..72eb4acaa 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs @@ -40,6 +40,15 @@ namespace Tango.MachineStudio.Common.Web } + /// + /// Initializes a new instance of the class. + /// + /// Other instance. + public MachineStudioWebClientBase(MachineStudioWebClientBase cloned) : base(cloned) + { + + } + /// /// Executes the CheckForUpdates action and returns Tango.MachineStudio.Common.Web.CheckForUpdatesResponse. /// diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs index 94f98feb2..c7e634ee8 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs @@ -35,7 +35,7 @@ namespace Tango.MachineStudio.UI private WpfGlobalExceptionTrapper exceptionTrapper; private LogManager LogManager = LogManager.Default; - public static String[] StartupArgs { get; set; } + public static String[] StartupArgs { get; set; } = Environment.GetCommandLineArgs().Skip(1).ToArray(); protected override void OnStartup(StartupEventArgs e) { diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs index 3cc5e8b49..c992d0768 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs @@ -96,7 +96,10 @@ namespace Tango.MachineStudio.UI.Authentication var settings = SettingsManager.Default.GetOrCreate(); - _client.Environment = settings.DeploymentSlot; + if (!App.StartupArgs.Contains("-webDebug")) + { + _client.Environment = settings.DeploymentSlot; + } var appVersion = AssemblyHelper.GetCurrentAssemblyVersion().ToString(); diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs index 3fffd69fd..25843d1c3 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Windows; using Tango.Core.DI; using Tango.Integration.ExternalBridge; @@ -71,7 +72,16 @@ namespace Tango.MachineStudio.UI TangoIOC.Default.Unregister(); - TangoIOC.Default.Register(new MachineStudioWebClient()); + + if (App.StartupArgs.Contains("-webDebug")) + { + TangoIOC.Default.Register(new MachineStudioWebClient("http://localhost:1111", null)); + } + else + { + TangoIOC.Default.Register(new MachineStudioWebClient()); + } + TangoIOC.Default.Register(new DefaultDispatcherProvider(Application.Current.Dispatcher)); TangoIOC.Default.Register(); TangoIOC.Default.Register(); @@ -84,7 +94,7 @@ namespace Tango.MachineStudio.UI TangoIOC.Default.Register(); TangoIOC.Default.Register(); TangoIOC.Default.Register(new TeamFoundationServiceExtendedClient("https://twinetfs.visualstudio.com", String.Empty, "szzfokrceo4rhd4eqi5qpmxn3pa5iwl3q7tlqd36l2m7smz2ynoa")); - + TangoIOC.Default.Register(); TangoIOC.Default.Register(); diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync-job.png b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync-job.png new file mode 100644 index 000000000..4e46ee447 Binary files /dev/null and b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync-job.png differ diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync.png b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync.png new file mode 100644 index 000000000..46059c5c0 Binary files /dev/null and b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync.png differ diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItem.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItem.cs new file mode 100644 index 000000000..4e3137e1c --- /dev/null +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItem.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.PPC.Common.Notifications; + +namespace Tango.PPC.Jobs.NotificationItems +{ + /// + /// Represents a simple text message notification item which can be inserted into the application notifications panel. + /// + /// + public class NewSynchronizardJobsNotificationItem : NotificationItem + { + /// + /// Initializes a new instance of the class. + /// + public NewSynchronizardJobsNotificationItem() + { + CanClose = true; + } + + /// + /// Gets or sets the view type. + /// + public override Type ViewType + { + get { return typeof(NewSynchronizardJobsNotificationItemView); } + } + } +} diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml new file mode 100644 index 000000000..23a64676b --- /dev/null +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml @@ -0,0 +1,26 @@ + + + + + + + + + + New job definitions were synchronized with your machine. Tap to refresh your job list. + + + + + + diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml.cs new file mode 100644 index 000000000..33db09386 --- /dev/null +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml.cs @@ -0,0 +1,30 @@ +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.PPC.Jobs.NotificationItems +{ + /// + /// Represents the view. + /// + /// + /// + public partial class NewSynchronizardJobsNotificationItemView : UserControl + { + public NewSynchronizardJobsNotificationItemView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj index 609a15de4..02343c0cc 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj @@ -124,6 +124,10 @@ Designer MSBuild:Compile + + MSBuild:Compile + Designer + Designer MSBuild:Compile @@ -228,6 +232,10 @@ + + + NewSynchronizardJobsNotificationItemView.xaml + Code @@ -486,10 +494,13 @@ + + + - + \ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs index a097084f7..dac8f9e49 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs @@ -593,6 +593,7 @@ namespace Tango.PPC.Jobs.ViewModels } Job.LastUpdated = DateTime.UtcNow; + Job.IsSynchronized = false; Job.JobStatus = BL.Enumerations.JobStatuses.Draft; await _db.SaveChangesAsync(); _current_job_string = Job.ToJobFileWhenLoaded().ToString(); diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs index 34d7e32cd..e80154413 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs @@ -36,6 +36,8 @@ using System.Windows.Media.Imaging; using Tango.Touch.Components; using Tango.PPC.Jobs.ViewContracts; using Tango.Core.ExtensionMethods; +using Tango.PPC.Common.Synchronization; +using Tango.PPC.Jobs.NotificationItems; namespace Tango.PPC.Jobs.ViewModels { @@ -483,7 +485,7 @@ namespace Tango.PPC.Jobs.ViewModels settings.LastJobType = vm.SelectedJobType; settings.LastJobColorSpace = vm.SelectedColorSpace; - + if (vm.SelectedColorSpace == ColorSpaces.Catalog) { settings.LastSelectedCatalogGuid = catalogVM.SelectedCatalog.Guid; @@ -728,6 +730,8 @@ namespace Tango.PPC.Jobs.ViewModels { _catalogs = (await c.ColorCatalogs.ToListAsync()).ToObservableCollection(); } + + MachineDataSynchronizer.SynchronizationEnded += MachineDataSynchronizer_SynchronizationEnded; } public override void OnNavigatedTo() @@ -871,6 +875,25 @@ namespace Tango.PPC.Jobs.ViewModels #endregion + #region Handle New Synchronized Jobs + + private void MachineDataSynchronizer_SynchronizationEnded(object sender, SynchronizationEndedEventArgs e) + { + if (e.NewChangedJobs > 0) + { + var item = NotificationProvider.PushNotification(); + item.Pressed += (_, __) => + { + LoadJobs(() => + { + NotificationProvider.ShowSuccess("Your job list is now synchronized."); + }); + }; + } + } + + #endregion + #region Color Profile Request private void ExternalBridgeService_ColorProfileRequest(object sender, ColorProfileRequestEventArgs e) diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs index 3cceba6c9..1af9b8609 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs @@ -122,6 +122,20 @@ namespace Tango.PPC.MachineSettings.ViewModels set { _defaultSpoolType = value; RaisePropertyChangedAuto(); } } + private bool _synchronizeJobs; + public bool SynchronizeJobs + { + get { return _synchronizeJobs; } + set { _synchronizeJobs = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + private bool _synchronizeDiagnostics; + public bool SynchronizeDiagnostics + { + get { return _synchronizeDiagnostics; } + set { _synchronizeDiagnostics = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + #endregion #region Commands @@ -136,12 +150,18 @@ namespace Tango.PPC.MachineSettings.ViewModels /// public RelayCommand DiscardCommand { get; set; } + /// + /// Gets or sets the synchronize command. + /// + public RelayCommand SynchronizeCommand { get; set; } + #endregion public MainViewVM() { SaveCommand = new RelayCommand(Save); DiscardCommand = new RelayCommand(Discard); + SynchronizeCommand = new RelayCommand(Synchronize, () => !MachineDataSynchronizer.IsSynchronizing && IsFree && (SynchronizeJobs || SynchronizeDiagnostics)); } private void Discard() @@ -166,6 +186,11 @@ namespace Tango.PPC.MachineSettings.ViewModels Settings.LockScreenPassword = LockScreenPassword; Settings.DefaultRmlGuid = DefaultRML?.Guid; Settings.DefaultSpoolTypeGuid = DefaultSpoolType?.Guid; + Settings.SynchronizeJobs = SynchronizeJobs; + Settings.SynchronizeDiagnostics = SynchronizeDiagnostics; + + MachineDataSynchronizer.IsEnabled = SynchronizeJobs || SynchronizeDiagnostics; + Settings.Save(); await MachineProvider.SaveMachine(); @@ -186,6 +211,13 @@ namespace Tango.PPC.MachineSettings.ViewModels } + public override void OnApplicationReady() + { + base.OnApplicationReady(); + MachineDataSynchronizer.SynchronizationStarted += (_, __) => InvalidateRelayCommands(); + MachineDataSynchronizer.SynchronizationEnded += (_, __) => InvalidateRelayCommands(); + } + public override void OnNavigatedTo() { base.OnNavigatedTo(); @@ -216,6 +248,9 @@ namespace Tango.PPC.MachineSettings.ViewModels DefaultRML = Adapter.Rmls.SingleOrDefault(x => x.Guid == Settings.DefaultRmlGuid); DefaultSpoolType = Adapter.SpoolTypes.SingleOrDefault(x => x.Guid == Settings.DefaultSpoolTypeGuid); + + SynchronizeJobs = Settings.SynchronizeJobs; + SynchronizeDiagnostics = Settings.SynchronizeDiagnostics; } private async void OnEnableRemoteAssistanceChanged() @@ -290,5 +325,29 @@ namespace Tango.PPC.MachineSettings.ViewModels { ExternalBridgeService.Enabled = EnableExternalBridge; } + + private async void Synchronize() + { + try + { + IsFree = false; + NotificationProvider.SetGlobalBusyMessage("Synchronizing..."); + + await MachineDataSynchronizer.Synchronize(); + + NotificationProvider.ReleaseGlobalBusyMessage(); + await NotificationProvider.ShowSuccess("Synchronization completed successfully."); + } + catch (Exception ex) + { + NotificationProvider.ReleaseGlobalBusyMessage(); + await NotificationProvider.ShowError($"Error occurred while trying to synchronize.\n{ex.FlattenMessage()}"); + } + finally + { + NotificationProvider.ReleaseGlobalBusyMessage(); + IsFree = true; + } + } } } 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 0d9a3cea1..e8bd657a0 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 @@ -11,9 +11,9 @@ xmlns:global="clr-namespace:Tango.PPC.MachineSettings" xmlns:local="clr-namespace:Tango.PPC.MachineSettings.Views" mc:Ignorable="d" - d:DesignHeight="2500" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}"> + d:DesignHeight="3000" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}"> - + @@ -195,6 +195,45 @@ + + + + + + + Synchronize Jobs + + + + Synchronize your jobs with twine's cloud services. + + + + + + + + + Synchronize Diagnostics Data + + + + Help us improve your experience using this system. + + + + + + + + + + Once enabled, synchronization occurres automatically in the background. you can choose to synchronize right now. + + + Synchronize Now + + diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/sync.png b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/sync.png new file mode 100644 index 000000000..46059c5c0 Binary files /dev/null and b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/sync.png differ diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj index 192b9ae11..e4261334a 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj @@ -98,10 +98,14 @@ + CatalogView.xaml + + SynchronizationView.xaml + PackagesView.xaml @@ -191,6 +195,10 @@ Designer MSBuild:Compile + + MSBuild:Compile + Designer + MSBuild:Compile Designer @@ -234,5 +242,8 @@ + + + \ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs index c79a10e79..05a04e2a6 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs @@ -21,6 +21,7 @@ namespace Tango.PPC.Technician TangoIOC.Default.Register(); TangoIOC.Default.Register(); TangoIOC.Default.Register(); + TangoIOC.Default.Register(); } /// @@ -88,5 +89,16 @@ namespace Tango.PPC.Technician return TangoIOC.Default.GetInstance(); } } + + /// + /// Gets the synchronization view vm. + /// + public static SynchronizationViewVM SynchronizationViewVM + { + get + { + return TangoIOC.Default.GetInstance(); + } + } } } diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SynchronizationViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SynchronizationViewVM.cs new file mode 100644 index 000000000..8036b99a4 --- /dev/null +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SynchronizationViewVM.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.Commands; +using Tango.PPC.Common; + +namespace Tango.PPC.Technician.ViewModels +{ + public class SynchronizationViewVM : PPCViewModel + { + public RelayCommand SynchronizeCommand { get; set; } + + public SynchronizationViewVM() + { + SynchronizeCommand = new RelayCommand(Synchronize, () => !MachineDataSynchronizer.IsSynchronizing); + } + + public override void OnApplicationStarted() + { + + } + + public override void OnApplicationReady() + { + base.OnApplicationReady(); + MachineDataSynchronizer.SynchronizationStarted += (_, __) => InvalidateRelayCommands(); + MachineDataSynchronizer.SynchronizationEnded += (_, __) => InvalidateRelayCommands(); + } + + private async void Synchronize() + { + try + { + await MachineDataSynchronizer.Synchronize(); + } + catch { } + } + } +} diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SystemViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SystemViewVM.cs index b46e566d1..13aeeb671 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SystemViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SystemViewVM.cs @@ -265,11 +265,11 @@ namespace Tango.PPC.Technician.ViewModels { using (ObservablesContext db = ObservablesContext.CreateDefault()) { - var jobs = await db.Jobs.Include(x => x.JobRuns).Where(x => x.MachineGuid == MachineProvider.Machine.Guid).ToListAsync(); + var jobRuns = await db.JobRuns.Where(x => x.MachineGuid == MachineProvider.Machine.Guid).ToListAsync(); - TotalDyeTime = TimeSpan.FromHours(jobs.SelectMany(x => x.JobRuns).Select(x => x.EndDate - x.StartDate).Sum(x => x.TotalHours)).ToString(@"hh\:mm\:ss"); + TotalDyeTime = TimeSpan.FromHours(jobRuns.Select(x => x.EndDate - x.StartDate).Sum(x => x.TotalHours)).ToString(@"hh\:mm\:ss"); - int meters = (int)jobs.SelectMany(x => x.JobRuns).Select(x => x.EndPosition).Sum(); + int meters = (int)jobRuns.Select(x => x.EndPosition).Sum(); TotalDyeMeters = $"{meters.ToString("N0")} meters"; } } diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml index c13c3e3eb..b0a86d938 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml @@ -50,7 +50,7 @@ Logging - + Display and investigate issues using application and embedded device logs. @@ -62,7 +62,7 @@ System - + Display system properties, perform system actions, reset, shutdown etc... @@ -74,7 +74,7 @@ Dispensers - + Perform manual dispensers homing priming. @@ -86,12 +86,24 @@ Installed Packages - + View the history of update packages installation. + + + + + + Synchronization + + View the current status and history of synchronization operations to the machine service. + + + + diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml index 733a2d713..2acadb32d 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml @@ -18,6 +18,7 @@ + diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml new file mode 100644 index 000000000..a0021d40e --- /dev/null +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + Synchronization + + + + + + + + Synchronize Now + Synchronization occurres automatically in the background. You can choose to synchronize now. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml.cs new file mode 100644 index 000000000..7193d66ff --- /dev/null +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.PPC.Technician.Views +{ + /// + /// Interaction logic for SynchronizationView.xaml + /// + public partial class SynchronizationView : UserControl + { + public SynchronizationView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Application/IPPCApplicationManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Application/IPPCApplicationManager.cs index 1474eaa04..8f1a80d37 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Application/IPPCApplicationManager.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Application/IPPCApplicationManager.cs @@ -95,6 +95,11 @@ namespace Tango.PPC.Common.Application /// Version Version { get; } + /// + /// Gets the firmware version. + /// + Version FirmwareVersion { get; } + /// /// Gets the application build date. /// diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs index 8cccc43a7..eae09a7e7 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs @@ -134,6 +134,12 @@ namespace Tango.PPC.Common.Connection try { await MachineOperator.Connect(); + + if (MachineOperator.DeviceInformation != null) + { + settings.FirmwareVersion = MachineOperator.DeviceInformation.Version; + settings.Save(); + } } catch (Exception) { @@ -156,6 +162,12 @@ namespace Tango.PPC.Common.Connection try { await MachineOperator.Connect(); + + if (MachineOperator.DeviceInformation != null) + { + settings.FirmwareVersion = MachineOperator.DeviceInformation.Version; + settings.Save(); + } } catch (Exception) { @@ -186,6 +198,12 @@ namespace Tango.PPC.Common.Connection LogManager.Log("Connecting machine operator..."); await MachineOperator.Connect(); + if (MachineOperator.DeviceInformation != null) + { + settings.FirmwareVersion = MachineOperator.DeviceInformation.Version; + settings.Save(); + } + await Task.Delay(1000); await MachineOperator.UploadHardwareConfiguration(Machine.Configuration.HardwareVersion, Machine.Configuration); } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs index f1c722d96..dfa9b833b 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs @@ -44,6 +44,7 @@ namespace Tango.PPC.Common.MachineSetup private IOperationSystemManager _windows_manager; private PPCWebClient _client; private List _logs; + private bool _isUpdating; #region Events @@ -93,7 +94,10 @@ namespace Tango.PPC.Common.MachineSetup private void LogManager_NewLog(object sender, LogItemBase e) { - _logs.Add(e); + if (_isUpdating) + { + _logs.Add(e); + } } #endregion @@ -136,6 +140,8 @@ namespace Tango.PPC.Common.MachineSetup LogManager.Log(xx, "Error notifying setup completed."); } } + + _isUpdating = false; } private async void OnCompleted(MachineSetupResult result, TaskCompletionSource completionSource, MachineSetupResponse response) @@ -157,6 +163,8 @@ namespace Tango.PPC.Common.MachineSetup LogManager.Log(xx, "Error notifying setup completed."); } } + + _isUpdating = false; } private String GetLogsStringAndClear() @@ -186,6 +194,8 @@ namespace Tango.PPC.Common.MachineSetup try { + _isUpdating = true; + LogManager.Log($"Starting machine setup for serial number {serialNumber}..."); var machineServiceAddress = SettingsManager.Default.GetOrCreate().GetMachineServiceAddress(); diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs index 7e742ceb6..30abb561f 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs @@ -880,6 +880,8 @@ namespace Tango.PPC.Common.MachineUpdate UpdateDBRequest request = new UpdateDBRequest(); request.SerialNumber = serialNumber; + request.ApplicationVersion = _app_manager.Version.ToString(); + request.FirmwareVersion = _app_manager.FirmwareVersion.ToString(); UpdateDBResponse update_response = null; diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs index d791d10d3..8805b75e4 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs @@ -179,6 +179,26 @@ namespace Tango.PPC.Common /// public String PreviousApplicationVersion { get; set; } + /// + /// Gets or sets a value indicating whether synchronize jobs with twine server. + /// + public bool SynchronizeJobs { get; set; } + + /// + /// Gets or sets a value indicating whether synchronize diagnostics data. + /// + public bool SynchronizeDiagnostics { get; set; } + + /// + /// Gets or sets the synchronization interval. + /// + public TimeSpan SynchronizationInterval { get; set; } + + /// + /// Gets or sets the known firmware version. + /// + public String FirmwareVersion { get; set; } + /// /// Gets the machine service address. /// @@ -214,6 +234,10 @@ namespace Tango.PPC.Common SupportedColorSpaces = new List(); SupportedJobTypes = new List(); PreviousApplicationVersion = "1.0.0.0"; + SynchronizeJobs = true; + SynchronizeDiagnostics = true; + SynchronizationInterval = TimeSpan.FromMinutes(60); + FirmwareVersion = "1.0.0.0"; } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs index 19bc6cd67..7992e6672 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs @@ -17,6 +17,7 @@ using Tango.PPC.Common.Notifications; using Tango.PPC.Common.Printing; using Tango.PPC.Common.RemoteAssistance; using Tango.PPC.Common.Storage; +using Tango.PPC.Common.Synchronization; using Tango.Settings; using Tango.SharedUI; using static Tango.SharedUI.Controls.NavigationControl; @@ -109,6 +110,12 @@ namespace Tango.PPC.Common [TangoInject] public IEventLogger EventLogger { get; set; } + /// + /// Gets or sets the machine data synchronizer. + /// + [TangoInject] + public IMachineDataSynchronizer MachineDataSynchronizer { get; set; } + private PPCSettings _settings; /// /// Gets the main PPC settings. diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs new file mode 100644 index 000000000..8260eb4b3 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs @@ -0,0 +1,554 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Timers; +using Tango.BL; +using Tango.PPC.Common.Web; +using System.Data.Entity; +using Tango.BL.DTO; +using Tango.PPC.Common.Connection; +using Tango.BL.Builders; +using Tango.Settings; +using Tango.Core; +using Tango.PPC.Common.Authentication; +using Tango.Logging; +using System.Diagnostics; +using Tango.BL.Enumerations; +using Tango.PPC.Common.Application; +using Tango.Core.DI; + +namespace Tango.PPC.Common.Synchronization +{ + public class DefaultMachineDataSynchronizer : ExtendedObject, IMachineDataSynchronizer + { + private Timer _synchTimer; + private PPCWebClient client; + private IMachineProvider _machineProvider; + private IAuthenticationProvider _authenticationProvider; + private List _logs; + private bool _synchronizedOnce; + + [TangoInject(TangoInjectMode.WhenAvailable)] + private IPPCApplicationManager _appManager; + + public event EventHandler CurrentStatusChanged; + public event EventHandler SynchronizationStarted; + public event EventHandler SynchronizationEnded; + + public int MaxJobs { get; set; } + public int MaxJobRuns { get; set; } + public int MaxMachinesEvents { get; set; } + + private SynchronizationStatus _currentStatus; + public SynchronizationStatus CurrentStatus + { + get { return _currentStatus; } + private set { _currentStatus = value; RaisePropertyChangedAuto(); } + } + + private SynchronizationStatus _lastStatus; + public SynchronizationStatus LastStatus + { + get { return _lastStatus; } + private set { _lastStatus = value; RaisePropertyChangedAuto(); } + } + + public SynchronizedObservableCollection StatusHistory { get; private set; } + + public TimeSpan Interval { get; set; } + + private bool _isEnabled; + public bool IsEnabled + { + get { return _isEnabled; } + set { _isEnabled = value; OnEnableChanged(); RaisePropertyChangedAuto(); } + } + + private bool _isSynchronizing; + public bool IsSynchronizing + { + get { return _isSynchronizing; } + set { _isSynchronizing = value; RaisePropertyChangedAuto(); } + } + + public DefaultMachineDataSynchronizer() + { + StatusHistory = new SynchronizedObservableCollection(); + + MaxJobs = 10; + MaxJobRuns = 100; + MaxMachinesEvents = 100; + + var settings = SettingsManager.Default.GetOrCreate(); + Interval = settings.SynchronizationInterval; + + _synchTimer = new Timer(Interval.TotalMilliseconds); + _synchTimer.Elapsed += _synchTimer_Elapsed; + _synchTimer.Enabled = true; + + ExecuteNewStatus(TimeSpan.FromMinutes(2)); + LastStatus = CurrentStatus; + } + + public DefaultMachineDataSynchronizer(PPCWebClient ppcWebClient, IMachineProvider machineProvider, IAuthenticationProvider authenticationProvider) : this() + { + _logs = new List(); + _machineProvider = machineProvider; + client = new PPCWebClient(ppcWebClient, TimeSpan.FromMinutes(10)); + _authenticationProvider = authenticationProvider; + + LogManager.NewLog += LogManager_NewLog; + } + + private void LogManager_NewLog(object sender, LogItemBase e) + { + if (IsSynchronizing) + { + _logs.Add(e); + } + } + + private String GetLogsStringAndClear() + { + String logsString = String.Join(Environment.NewLine, _logs.ToList().Select(x => x.ToString())); + _logs.Clear(); + return logsString; + } + + private void OnEnableChanged() + { + _synchTimer.Interval = Interval.TotalMilliseconds; + + if (IsEnabled) + { + CurrentStatus.State = SynchronizationState.Pending; + } + else + { + CurrentStatus.State = SynchronizationState.Disabled; + } + } + + private void _synchTimer_Elapsed(object sender, ElapsedEventArgs e) + { + _synchTimer.Interval = Interval.TotalMilliseconds; + + try + { + Synchronize().GetAwaiter().GetResult(); + } + catch { } + } + + private async Task CreateUploadMachineDataRequest(bool syncJobs, bool syncDiagnostics) + { + UploadMachineDataRequest request = new UploadMachineDataRequest(); + + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + if (syncJobs) + { + LogManager.Log("Checking Jobs..."); + + var jobs = await new JobsCollectionBuilder(db).Set(x => !x.IsSynchronized).WithSegments().WithBrushStops().Query(x => x.Take(MaxJobs).OrderByDescending(z => z.LastUpdated)).BuildListAsync(); + List dtos = new List(); + + foreach (var job in jobs) + { + var dto = JobDTO.FromObservable(job); + request.Jobs.Add(dto); + } + } + + if (syncDiagnostics) + { + LogManager.Log("Checking Job Runs..."); + + var jobRuns = await db.JobRuns.Where(x => !x.IsSynchronized).Take(MaxJobRuns).OrderByDescending(x => x.LastUpdated).ToListAsync(); + List dtos = new List(); + + foreach (var jobRun in jobRuns) + { + var dto = JobRunDTO.FromObservable(jobRun); + request.JobRuns.Add(dto); + } + } + + if (syncDiagnostics) + { + LogManager.Log("Checking Events..."); + + var machineEvents = await db.MachinesEvents.Where(x => !x.IsSynchronized).Take(MaxMachinesEvents).OrderByDescending(x => x.LastUpdated).ToListAsync(); + List dtos = new List(); + + foreach (var machineEvent in machineEvents) + { + machineEvent.IsSynchronized = true; + var dto = MachinesEventDTO.FromObservable(machineEvent); + request.MachineEvents.Add(dto); + } + } + } + + return request; + } + + private async Task FinalizeMachineDataUpload(UploadMachineDataRequest request, UploadMachineDataResponse response) + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + //Finalize jobs + foreach (var job in request.Jobs) + { + var failedJob = response.FailedJobs.SingleOrDefault(x => x.Guid == job.Guid); + + if (failedJob == null) + { + var dbJob = await db.Jobs.SingleOrDefaultAsync(x => x.Guid == job.Guid); + dbJob.IsSynchronized = true; + } + else + { + LogManager.Log($"Synchronization Error - Job '{job.Name}' cannot be stored on the server due to the following reason:\n{failedJob.Reason}", LogCategory.Error); + } + } + + //Finalize job runs + foreach (var jobRun in request.JobRuns) + { + var failedJobRun = response.FailedJobRuns.SingleOrDefault(x => x.Guid == jobRun.Guid); + + if (failedJobRun == null) + { + var dbJobRun = await db.JobRuns.SingleOrDefaultAsync(x => x.Guid == jobRun.Guid); + dbJobRun.IsSynchronized = true; + } + else + { + LogManager.Log($"Synchronization Error - JobRun '{jobRun.ID}' cannot be stored on the server due to the following reason:\n{failedJobRun.Reason}", LogCategory.Error); + } + } + + //Finalize machine events + foreach (var machineEvent in request.MachineEvents) + { + var failedMachineEvent = response.FailedMachineEvents.SingleOrDefault(x => x.Guid == machineEvent.Guid); + + if (failedMachineEvent == null) + { + var dbMachineEvent = await db.MachinesEvents.SingleOrDefaultAsync(x => x.Guid == machineEvent.Guid); + dbMachineEvent.IsSynchronized = true; + } + else + { + LogManager.Log($"Synchronization Error - Event '{machineEvent.ID}' cannot be stored on the server due to the following reason:\n{failedMachineEvent.Reason}", LogCategory.Error); + } + } + + await db.SaveChangesAsync(); + } + } + + private async Task DownloadMachineData(bool syncJobs, bool syncDiagnostics) + { + return await client.DownloadMachineData(new DownloadMachineDataRequest() + { + RequestJobs = syncJobs, + RequestJobRuns = syncDiagnostics, + RequestMachineEvents = syncDiagnostics, + MaxJobs = MaxJobs, + MaxJobRuns = MaxJobRuns, + MaxMachinesEvents = MaxMachinesEvents, + }); + } + + private async Task InsertReplaceMachineData(DownloadMachineDataResponse response) + { + NotifyMachineDataDownloadCompletedRequest request = new NotifyMachineDataDownloadCompletedRequest(); + + //Insert/Replace Jobs. + if (response.Jobs.Count > 0) + { + LogManager.Log("Inserting/Replacing Jobs..."); + } + foreach (var dto in response.Jobs) + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + try + { + var job = dto.ToObservable(); + + job.ID = 0; + job.UserGuid = _authenticationProvider.CurrentUser.Guid; + job.CustomerGuid = null; + job.IsSynchronized = true; + + var existingJob = await db.Jobs.SingleOrDefaultAsync(x => x.Guid == job.Guid); + + if (existingJob == null) + { + db.Jobs.Add(job); + await db.SaveChangesAsync(); + } + else if (job.LastUpdated > existingJob.LastUpdated) + { + existingJob.Delete(db); + db.Jobs.Add(job); + await db.SaveChangesAsync(); + } + + request.SynchronizedJobs.Add(job.Guid); + } + catch (Exception ex) + { + LogManager.Log($"Synchronization Error - Job '{dto.Name}' cannot be stored locally due to the following reason:\n{ex.FlattenMessage()}", LogCategory.Error); + } + } + } + + //Insert JobRuns. + if (response.JobRuns.Count > 0) + { + LogManager.Log("Inserting/Replacing Job Runs..."); + } + foreach (var dto in response.JobRuns) + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + try + { + var run = dto.ToObservable(); + run.ID = 0; + run.IsSynchronized = true; + + if (await db.JobRuns.SingleOrDefaultAsync(x => x.Guid == run.Guid) == null) + { + db.JobRuns.Add(run); + await db.SaveChangesAsync(); + } + + request.SynchronizedJobRuns.Add(run.Guid); + } + catch (Exception ex) + { + LogManager.Log($"Synchronization Error - JobRun '{dto.ID}' cannot be stored locally due to the following reason:\n{ex.FlattenMessage()}", LogCategory.Error); + } + } + } + + //Insert MachineEvents. + if (response.MachineEvents.Count > 0) + { + LogManager.Log("Inserting/Replacing Events..."); + } + foreach (var dto in response.MachineEvents) + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + try + { + var ev = dto.ToObservable(); + ev.ID = 0; + ev.UserGuid = _authenticationProvider.CurrentUser.Guid; + ev.IsSynchronized = true; + + if (await db.MachinesEvents.SingleOrDefaultAsync(x => x.Guid == ev.Guid) == null) + { + db.MachinesEvents.Add(ev); + await db.SaveChangesAsync(); + } + + request.SynchronizedMachineEvents.Add(ev.Guid); + } + catch (Exception ex) + { + LogManager.Log($"Synchronization Error - Event '{dto.ID}' cannot be stored locally due to the following reason:\n{ex.FlattenMessage()}", LogCategory.Error); + } + } + } + + return request; + } + + public async Task Synchronize() + { + _synchronizedOnce = true; + + if (!IsEnabled || IsSynchronizing) return; + + var settings = SettingsManager.Default.GetOrCreate(); + + var syncJobs = settings.SynchronizeJobs; + var syncDiagnostics = settings.SynchronizeDiagnostics; + + if (!syncJobs && !syncDiagnostics) return; + + IsSynchronizing = true; + SynchronizationStarted?.Invoke(this, new EventArgs()); + + _logs.Clear(); + + _synchTimer.Stop(); + + LogManager.Log("Starting machine data synchronization..."); + LogManager.Log($"Synchronization interval: {Interval}."); + + CurrentStatus.StartDateTime = DateTime.Now; + UpdateCurrentStatus(SynchronizationState.Synchronizing, "Starting synchronization..."); + + Stopwatch watch = new Stopwatch(); + watch.Start(); + + String notifyToken = null; + + int newChangedJobs = 0; + int newJobRuns = 0; + int newMachineEvents = 0; + + try + { + LogManager.Log("Authenticating with machine service..."); + + UpdateCurrentStatus(SynchronizationState.Synchronizing, "Authenticating with machine service..."); + + if (!this.client.IsAuthenticated) + { + await this.client.Login(new LoginRequest() + { + Mode = LoginMode.Machine, + SerialNumber = _machineProvider.Machine.SerialNumber, + }); + } + + UpdateCurrentStatus(SynchronizationState.Synchronizing, "Preparing machine data for upload..."); + LogManager.Log("Preparing machine data for upload..."); + var request = await CreateUploadMachineDataRequest(syncJobs, syncDiagnostics); + request.ApplicationVersion = _appManager.Version.ToString(); + request.FirmwareVersion = _appManager.FirmwareVersion.ToString(); + + UpdateCurrentStatus(SynchronizationState.Synchronizing, "Uploading machine data..."); + LogManager.Log($"Uploading machine data:\nJobs: {request.Jobs.Count}\nJob Runs: {request.JobRuns.Count}\nEvents: {request.MachineEvents.Count}"); + var response = await this.client.UploadMachineData(request); + notifyToken = response.NotifyCompletedToken; + LogManager.Log($"Upload response received:\nFailed Jobs: {response.FailedJobs.Count}\nFailed Job Runs: {response.FailedJobRuns.Count}\nFailed Events: {response.FailedMachineEvents.Count}"); + LogManager.Log("Finalizing upload..."); + UpdateCurrentStatus(SynchronizationState.Synchronizing, "Finalizing upload..."); + await FinalizeMachineDataUpload(request, response); + + UpdateCurrentStatus(SynchronizationState.Synchronizing, "Downloading machine data from service..."); + LogManager.Log("Downloading machine data from server..."); + var downloadResponse = await DownloadMachineData(syncJobs, syncDiagnostics); + + newChangedJobs = downloadResponse.Jobs.Count; + newJobRuns = downloadResponse.JobRuns.Count; + newMachineEvents = downloadResponse.MachineEvents.Count; + + LogManager.Log($"Download response received:\nJobs: {downloadResponse.Jobs.Count}\nJob Runs: {downloadResponse.JobRuns.Count}\nEvents: {downloadResponse.MachineEvents.Count}"); + UpdateCurrentStatus(SynchronizationState.Synchronizing, "Updating local database..."); + LogManager.Log("Updating local database..."); + var notifyRequest = await InsertReplaceMachineData(downloadResponse); + LogManager.Log($"Finalizing download:\nSynchronized Jobs: {notifyRequest.SynchronizedJobs.Count}\nSynchronized Job Runs: {notifyRequest.SynchronizedJobRuns.Count}\nSynchronized Events: {notifyRequest.SynchronizedMachineEvents.Count}"); + UpdateCurrentStatus(SynchronizationState.Synchronizing, "Finalizing download..."); + var notifyResponse = await this.client.NotifyMachineDataDownloadCompleted(notifyRequest); + + if (notifyToken != null) + { + try + { + await client.NotifyUpdateCompleted(new MachineUpdateCompletedRequest() + { + Token = notifyToken, + Status = TangoUpdateStatuses.SynchronizationCompleted, + }); + } + catch (Exception ex) + { + LogManager.Log(ex, "Synchronization completed successfully but an error occurred when trying to notify about the completion."); + } + } + + LogManager.Log("Machine data synchronization completed successfully."); + UpdateCurrentStatus(SynchronizationState.Completed, "Synchronization completed successfully.", null, watch.Elapsed); + } + catch (Exception ex) + { + if (notifyToken != null) + { + try + { + await client.NotifyUpdateCompleted(new MachineUpdateCompletedRequest() + { + Token = notifyToken, + Status = TangoUpdateStatuses.SynchronizationFailed, + FailedReason = ex.FlattenMessage(), + FailedLog = GetLogsStringAndClear(), + }); + } + catch (Exception ee) + { + LogManager.Log(ee, "Synchronization completed successfully but an error occurred when trying to notify about the completion."); + } + } + + UpdateCurrentStatus(SynchronizationState.Failed, "Synchronization failed.", ex.FlattenMessage(), watch.Elapsed); + throw LogManager.Log(ex, "Error occurred while synchronizing machine data."); + } + finally + { + watch.Stop(); + LogManager.Log($"Synchronization duration: {watch.Elapsed}."); + LastStatus = CurrentStatus; + CreateNewStatus(); + IsSynchronizing = false; + SynchronizationEnded?.Invoke(this, new SynchronizationEndedEventArgs() + { + NewChangedJobs = newChangedJobs, + NewJobRuns = newJobRuns, + NewMachineEvents = newMachineEvents, + }); + } + + _synchTimer.Start(); + } + + private void CreateNewStatus() + { + CurrentStatus = new SynchronizationStatus(); + CurrentStatus.State = SynchronizationState.Pending; + CurrentStatus.StartDateTime = DateTime.Now.Add(Interval); + StatusHistory.Insert(0, CurrentStatus); + } + + private async void ExecuteNewStatus(TimeSpan delay) + { + CurrentStatus = new SynchronizationStatus(); + CurrentStatus.State = SynchronizationState.Pending; + CurrentStatus.StartDateTime = DateTime.Now.Add(delay); + StatusHistory.Insert(0, CurrentStatus); + await Task.Delay(delay); + try + { + if (!_synchronizedOnce) + { + await Synchronize(); + } + } + catch { } + } + + private void UpdateCurrentStatus(SynchronizationState state, String message, String errorReason = null, TimeSpan? duration = null) + { + CurrentStatus.State = state; + CurrentStatus.Message = message; + CurrentStatus.ErrorReason = errorReason; + CurrentStatus.Duration = duration; + CurrentStatusChanged?.Invoke(this, new SynchronizationStatusChangedEventArgs() + { + Status = CurrentStatus, + }); + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/IMachineDataSynchronizer.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/IMachineDataSynchronizer.cs new file mode 100644 index 000000000..bfd527a05 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/IMachineDataSynchronizer.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; + +namespace Tango.PPC.Common.Synchronization +{ + public interface IMachineDataSynchronizer + { + event EventHandler SynchronizationStarted; + event EventHandler SynchronizationEnded; + event EventHandler CurrentStatusChanged; + int MaxJobs { get; set; } + int MaxJobRuns { get; set; } + int MaxMachinesEvents { get; set; } + SynchronizationStatus CurrentStatus { get; } + SynchronizationStatus LastStatus { get; } + SynchronizedObservableCollection StatusHistory { get; } + TimeSpan Interval { get; set; } + bool IsEnabled { get; set; } + bool IsSynchronizing { get; } + Task Synchronize(); + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationEndedEventArgs.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationEndedEventArgs.cs new file mode 100644 index 000000000..4b8040e95 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationEndedEventArgs.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.PPC.Common.Synchronization +{ + public class SynchronizationEndedEventArgs : EventArgs + { + public int NewChangedJobs { get; set; } + public int NewJobRuns { get; set; } + public int NewMachineEvents { get; set; } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationState.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationState.cs new file mode 100644 index 000000000..5797f449f --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationState.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.PPC.Common.Synchronization +{ + public enum SynchronizationState + { + [Description("Pending...")] + Pending, + [Description("Synchronizing...")] + Synchronizing, + [Description("Failed")] + Failed, + [Description("Completed")] + Completed, + [Description("Disabled")] + Disabled + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatus.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatus.cs new file mode 100644 index 000000000..5b1d5d1d2 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatus.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; + +namespace Tango.PPC.Common.Synchronization +{ + public class SynchronizationStatus : ExtendedObject + { + private SynchronizationState _state; + public SynchronizationState State + { + get { return _state; } + set { _state = value; RaisePropertyChangedAuto(); } + } + + private String _message; + public String Message + { + get { return _message; } + set { _message = value; RaisePropertyChangedAuto(); } + } + + private String _errorReason; + public String ErrorReason + { + get { return _errorReason; } + set { _errorReason = value; RaisePropertyChangedAuto(); } + } + + private TimeSpan? _duration; + public TimeSpan? Duration + { + get { return _duration; } + set { _duration = value; RaisePropertyChangedAuto(); } + } + + private DateTime _startDateTime; + public DateTime StartDateTime + { + get { return _startDateTime; } + set { _startDateTime = value; RaisePropertyChangedAuto(); } + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatusChangedEventArgs.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatusChangedEventArgs.cs new file mode 100644 index 000000000..1f0a9a27f --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatusChangedEventArgs.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.PPC.Common.Synchronization +{ + public class SynchronizationStatusChangedEventArgs : EventArgs + { + public SynchronizationStatus Status { get; set; } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj index d38b9c8e9..b781e3c9a 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj @@ -156,6 +156,12 @@ + + + + + + @@ -177,6 +183,8 @@ + + @@ -192,6 +200,7 @@ + @@ -226,8 +235,12 @@ + + + + @@ -406,7 +419,7 @@ - + \ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataRequest.cs new file mode 100644 index 000000000..66fca8e36 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataRequest.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.DTO; +using Tango.Transport.Web; + +namespace Tango.PPC.Common.Web +{ + public class DownloadMachineDataRequest : WebRequestMessage + { + public bool RequestJobs { get; set; } + public bool RequestJobRuns { get; set; } + public bool RequestMachineEvents { get; set; } + + public int MaxJobs { get; set; } + public int MaxJobRuns { get; set; } + public int MaxMachinesEvents { get; set; } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataResponse.cs new file mode 100644 index 000000000..5c3f7ba78 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataResponse.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.DTO; +using Tango.Transport.Web; + +namespace Tango.PPC.Common.Web +{ + public class DownloadMachineDataResponse : WebResponseMessage + { + public List Jobs { get; set; } + public List JobRuns { get; set; } + public List MachineEvents { get; set; } + + public DownloadMachineDataResponse() + { + Jobs = new List(); + JobRuns = new List(); + MachineEvents = new List(); + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedRequest.cs new file mode 100644 index 000000000..fc135c234 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedRequest.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.DTO; +using Tango.Transport.Web; + +namespace Tango.PPC.Common.Web +{ + public class NotifyMachineDataDownloadCompletedRequest : WebRequestMessage + { + public List SynchronizedJobs { get; set; } + public List SynchronizedJobRuns { get; set; } + public List SynchronizedMachineEvents { get; set; } + + public NotifyMachineDataDownloadCompletedRequest() + { + SynchronizedJobs = new List(); + SynchronizedJobRuns = new List(); + SynchronizedMachineEvents = new List(); + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedResponse.cs new file mode 100644 index 000000000..6d5769885 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedResponse.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.DTO; +using Tango.Transport.Web; + +namespace Tango.PPC.Common.Web +{ + public class NotifyMachineDataDownloadCompletedResponse : WebResponseMessage + { + + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClient.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClient.cs index 52c9fdef3..318512fbb 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClient.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClient.cs @@ -30,5 +30,10 @@ namespace Tango.PPC.Common.Web public PPCWebClient(string address, string token) : base(address, token) { } + + public PPCWebClient(PPCWebClient other, TimeSpan requestTimeout) : base(other) + { + RequestTimeout = requestTimeout; + } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClientBase.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClientBase.cs index 5520f8b5a..ff972acb2 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClientBase.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClientBase.cs @@ -40,6 +40,15 @@ namespace Tango.PPC.Common.Web } + /// + /// Initializes a new instance of the class. + /// + /// Other instance. + public PPCWebClientBase(PPCWebClientBase cloned) : base(cloned) + { + + } + /// /// Executes the MachineSetup action and returns Tango.PPC.Common.Web.MachineSetupResponse. /// @@ -85,6 +94,33 @@ namespace Tango.PPC.Common.Web return Post("UpdateDB", request); } + /// + /// Executes the UploadMachineData action and returns Tango.PPC.Common.Web.UploadMachineDataResponse. + /// + /// + public Task UploadMachineData(Tango.PPC.Common.Web.UploadMachineDataRequest request) + { + return Post("UploadMachineData", request); + } + + /// + /// Executes the DownloadMachineData action and returns Tango.PPC.Common.Web.DownloadMachineDataResponse. + /// + /// + public Task DownloadMachineData(Tango.PPC.Common.Web.DownloadMachineDataRequest request) + { + return Post("DownloadMachineData", request); + } + + /// + /// Executes the NotifyMachineDataDownloadCompleted action and returns Tango.PPC.Common.Web.NotifyMachineDataDownloadCompletedResponse. + /// + /// + public Task NotifyMachineDataDownloadCompleted(Tango.PPC.Common.Web.NotifyMachineDataDownloadCompletedRequest request) + { + return Post("NotifyMachineDataDownloadCompleted", request); + } + /// /// Executes the GetLatestVersion action and returns Tango.PPC.Common.Web.LatestVersionResponse. /// diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/SynchronizationFailedEntity.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/SynchronizationFailedEntity.cs new file mode 100644 index 000000000..c50044cbe --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/SynchronizationFailedEntity.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.PPC.Common.Web +{ + public class SynchronizationFailedEntity + { + public String Guid { get; set; } + public String Reason { get; set; } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UpdateDBRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UpdateDBRequest.cs index f3b4ccb34..c78f6199e 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UpdateDBRequest.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UpdateDBRequest.cs @@ -10,5 +10,7 @@ namespace Tango.PPC.Common.Web public class UpdateDBRequest : WebRequestMessage { public String SerialNumber { get; set; } + public String ApplicationVersion { get; set; } + public String FirmwareVersion { get; set; } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataRequest.cs new file mode 100644 index 000000000..dc0b05988 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataRequest.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.DTO; +using Tango.Transport.Web; + +namespace Tango.PPC.Common.Web +{ + public class UploadMachineDataRequest : WebRequestMessage + { + public List Jobs { get; set; } + public List JobRuns { get; set; } + public List MachineEvents { get; set; } + public String ApplicationVersion { get; set; } + public String FirmwareVersion { get; set; } + + public UploadMachineDataRequest() + { + Jobs = new List(); + JobRuns = new List(); + MachineEvents = new List(); + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataResponse.cs new file mode 100644 index 000000000..e4dda4013 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataResponse.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.DTO; +using Tango.Transport.Web; + +namespace Tango.PPC.Common.Web +{ + public class UploadMachineDataResponse : WebResponseMessage + { + public List FailedJobs { get; set; } + public List FailedJobRuns { get; set; } + public List FailedMachineEvents { get; set; } + public String NotifyCompletedToken { get; set; } + + public UploadMachineDataResponse() + { + FailedJobs = new List(); + FailedJobRuns = new List(); + FailedMachineEvents = new List(); + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/App.config b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/App.config new file mode 100644 index 000000000..731f6de6c --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Program.cs b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Program.cs new file mode 100644 index 000000000..d77192de2 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Program.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.SQLExaminer; + +namespace Tango.PPC.SchemaSynchronizer.CLI +{ + class Program + { + static void Main(string[] args) + { + Core.DataSource source = new Core.DataSource(); + source.Address = "localhost\\SQLEXPRESS"; + source.Catalog = "Tango"; + + Core.DataSource target = new Core.DataSource(); + target.Address = "localhost\\SQLPPC"; + target.Catalog = "Tango"; + + ExaminerConfigurationBuilder builder = new ExaminerConfigurationBuilder(ExaminerConfigurationType.Schema); + + builder. + SetSource(source). + SetTarget(target). + Synchronize(); + + var config = builder.Build(); + + ExaminerProcess process = new ExaminerProcess(config, ExaminerProcessType.Schema); + process.Progress += (x, msg) => + { + Console.WriteLine(msg); + }; + var result = process.Execute().Result; + + if (result.ExitCode == ExaminerProcessExitCode.Success) + { + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine("Completed!"); + } + else + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("Failed!"); + } + + Console.ReadLine(); + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Properties/AssemblyInfo.cs b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..61246489d --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 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.PPC.SchemaSynchronizer.CLI")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Tango.PPC.SchemaSynchronizer.CLI")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[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)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f3746f2b-e4ae-498b-9d42-74f95d992460")] + +// 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/PPC/Tango.PPC.SchemaSynchronizer.CLI/Tango.PPC.SchemaSynchronizer.CLI.csproj b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Tango.PPC.SchemaSynchronizer.CLI.csproj new file mode 100644 index 000000000..529815ba2 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Tango.PPC.SchemaSynchronizer.CLI.csproj @@ -0,0 +1,63 @@ + + + + + Debug + AnyCPU + {F3746F2B-E4AE-498B-9D42-74F95D992460} + Exe + Tango.PPC.SchemaSynchronizer.CLI + Tango.PPC.SchemaSynchronizer.CLI + v4.6.1 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + {a34ee0f0-649d-41c8-8489-b6f1cc6924ee} + Tango.Core + + + {e1e66ed9-597d-45fa-8048-de90a6930484} + Tango.SQLExaminer + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs index 44b6ffded..70ba4b695 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs @@ -33,6 +33,7 @@ using Tango.Core.Threading; using Tango.PPC.Common.Messages; using Tango.Core.ExtensionMethods; using Tango.PPC.Common.Navigation; +using Tango.PPC.Common.Synchronization; namespace Tango.PPC.UI.PPCApplication { @@ -50,6 +51,7 @@ namespace Tango.PPC.UI.PPCApplication private IEventLogger _eventLogger; private IPPCModuleLoader _moduleLoader; private INotificationProvider _notificationProvider; + private IMachineDataSynchronizer _machineDataSynchronizer; private WatchDogServer _watchdogServer; private ObservablesContext _machineContext; private ActionTimer _screenLockTimer; @@ -146,16 +148,28 @@ namespace Tango.PPC.UI.PPCApplication set { _isScreenLocked = value; RaisePropertyChangedAuto(); } } + /// + /// Gets the firmware version. + /// + public Version FirmwareVersion + { + get + { + return Version.Parse(SettingsManager.Default.GetOrCreate().FirmwareVersion); + } + } + /// /// Initializes a new instance of the class. /// - public DefaultPPCApplicationManager(IMachineProvider machineProvider, IDispatcherProvider dispatcherProvider, IEventLogger eventLogger, IPPCModuleLoader moduleLoader, INotificationProvider notificationProvider) + public DefaultPPCApplicationManager(IMachineProvider machineProvider, IDispatcherProvider dispatcherProvider, IEventLogger eventLogger, IPPCModuleLoader moduleLoader, INotificationProvider notificationProvider, IMachineDataSynchronizer machineDataSynchronizer) { _notificationProvider = notificationProvider; _machineProvider = machineProvider; _dispatcher = dispatcherProvider; _eventLogger = eventLogger; _moduleLoader = moduleLoader; + _machineDataSynchronizer = machineDataSynchronizer; if (!DesignMode) { @@ -248,6 +262,8 @@ namespace Tango.PPC.UI.PPCApplication LogManager.Log("Loading machine from database..."); _machineContext = ObservablesContext.CreateDefault(); _machine = new MachineBuilder(_machineContext).SetFirst().WithVersion().WithSettings().WithOrganization().WithConfiguration().WithSpools().WithCats().Build(); + + } initialized = true; @@ -349,6 +365,9 @@ namespace Tango.PPC.UI.PPCApplication LogManager.Log("Initializing Machine Provider..."); _machineProvider.Init(_machine, _machineContext); + LogManager.Log("Starting Machine Data Synchronizer..."); + _machineDataSynchronizer.IsEnabled = true; + LogManager.Log("Applications initialization completed!"); LogManager.Log("Checking for un-notified PPC view models..."); diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs index 60bce4e20..49157a998 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Windows; using Tango.Core.DI; using Tango.Integration.ExternalBridge; @@ -21,6 +22,7 @@ using Tango.PPC.Common.OS; using Tango.PPC.Common.Printing; using Tango.PPC.Common.RemoteAssistance; using Tango.PPC.Common.Storage; +using Tango.PPC.Common.Synchronization; using Tango.PPC.Common.Threading; using Tango.PPC.Common.UpdatePackages; using Tango.PPC.Common.UWF; @@ -75,8 +77,17 @@ namespace Tango.PPC.UI TangoIOC.Default.Unregister(); TangoIOC.Default.Unregister(); TangoIOC.Default.Unregister(); + TangoIOC.Default.Unregister(); + + if (App.StartupArgs.Contains("-webDebug")) + { + TangoIOC.Default.Register(new PPCWebClient("http://localhost:1111", null)); + } + else + { + TangoIOC.Default.Register(new PPCWebClient()); + } - TangoIOC.Default.Register(new PPCWebClient()); TangoIOC.Default.Register(new DefaultDispatcherProvider(Application.Current.Dispatcher)); TangoIOC.Default.Register(); TangoIOC.Default.Register(); @@ -84,6 +95,7 @@ namespace Tango.PPC.UI TangoIOC.Default.Register(); TangoIOC.Default.Register(); TangoIOC.Default.Register(); + TangoIOC.Default.Register(); TangoIOC.Default.Register(); TangoIOC.Default.Register(); TangoIOC.Default.Register(); diff --git a/Software/Visual_Studio/Tango.BL/Builders/EntityCollectionBuilderBase.cs b/Software/Visual_Studio/Tango.BL/Builders/EntityCollectionBuilderBase.cs index a0cd24511..d4d65c16d 100644 --- a/Software/Visual_Studio/Tango.BL/Builders/EntityCollectionBuilderBase.cs +++ b/Software/Visual_Studio/Tango.BL/Builders/EntityCollectionBuilderBase.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; @@ -13,6 +14,7 @@ namespace Tango.BL.Builders private List> _steps; private List, IQueryable>>> _querySteps; private bool _entity_set; + private Func, IQueryable> _appendQuery; protected IEnumerable Entities { get; set; } @@ -38,6 +40,11 @@ namespace Tango.BL.Builders query = queryStep.Value(query); } + if (_appendQuery != null) + { + query = _appendQuery(query); + } + Entities = query.ToList(); }); @@ -58,6 +65,11 @@ namespace Tango.BL.Builders query = queryStep.Value(query); } + if (_appendQuery != null) + { + query = _appendQuery(query); + } + Entities = query.ToList(); }); @@ -71,6 +83,12 @@ namespace Tango.BL.Builders return query; } + public TBuilder Query(Func, IQueryable> query) + { + _appendQuery = query; + return this as TBuilder; + } + protected void CommitSteps() { foreach (var step in _steps.ToList().DistinctBy(x => x.Key).OrderBy(x => x.Key)) @@ -104,6 +122,18 @@ namespace Tango.BL.Builders return Entities.ToSynchronizedObservableCollection(); } + public List BuildList() + { + if (!_entity_set) + { + throw new InvalidOperationException("Could not build entity. Entity was not set."); + } + + CommitSteps(); + + return Entities.ToList(); + } + public Task> BuildAsync() { return Task.Factory.StartNew>(() => @@ -111,5 +141,13 @@ namespace Tango.BL.Builders return Build(); }); } + + public Task> BuildListAsync() + { + return Task.Factory.StartNew>(() => + { + return BuildList(); + }); + } } } diff --git a/Software/Visual_Studio/Tango.BL/DTO/JobDTO.cs b/Software/Visual_Studio/Tango.BL/DTO/JobDTO.cs index 137d7b4b3..7ee6c9bb0 100644 --- a/Software/Visual_Studio/Tango.BL/DTO/JobDTO.cs +++ b/Software/Visual_Studio/Tango.BL/DTO/JobDTO.cs @@ -9,6 +9,11 @@ namespace Tango.BL.DTO { public class JobDTO : JobDTOBase { + public List Segments { get; set; } + public JobDTO() + { + Segments = new List(); + } } } diff --git a/Software/Visual_Studio/Tango.BL/DTO/JobDTOBase.cs b/Software/Visual_Studio/Tango.BL/DTO/JobDTOBase.cs index f2842c4fd..c3c418f1f 100644 --- a/Software/Visual_Studio/Tango.BL/DTO/JobDTOBase.cs +++ b/Software/Visual_Studio/Tango.BL/DTO/JobDTOBase.cs @@ -274,5 +274,13 @@ namespace Tango.BL.DTO get; set; } + /// + /// is synchronized + /// + public Boolean IsSynchronized + { + get; set; + } + } } diff --git a/Software/Visual_Studio/Tango.BL/DTO/JobRunDTOBase.cs b/Software/Visual_Studio/Tango.BL/DTO/JobRunDTOBase.cs index 9726f16a7..b47ce3ea9 100644 --- a/Software/Visual_Studio/Tango.BL/DTO/JobRunDTOBase.cs +++ b/Software/Visual_Studio/Tango.BL/DTO/JobRunDTOBase.cs @@ -82,5 +82,13 @@ namespace Tango.BL.DTO get; set; } + /// + /// is synchronized + /// + public Boolean IsSynchronized + { + get; set; + } + } } diff --git a/Software/Visual_Studio/Tango.BL/DTO/MachinesEventDTOBase.cs b/Software/Visual_Studio/Tango.BL/DTO/MachinesEventDTOBase.cs index 8a044f7e8..e990f2a31 100644 --- a/Software/Visual_Studio/Tango.BL/DTO/MachinesEventDTOBase.cs +++ b/Software/Visual_Studio/Tango.BL/DTO/MachinesEventDTOBase.cs @@ -69,5 +69,13 @@ namespace Tango.BL.DTO get; set; } + /// + /// is synchronized + /// + public Boolean IsSynchronized + { + get; set; + } + } } diff --git a/Software/Visual_Studio/Tango.BL/DTO/SegmentDTO.cs b/Software/Visual_Studio/Tango.BL/DTO/SegmentDTO.cs index 1db99be23..09f581db2 100644 --- a/Software/Visual_Studio/Tango.BL/DTO/SegmentDTO.cs +++ b/Software/Visual_Studio/Tango.BL/DTO/SegmentDTO.cs @@ -9,6 +9,11 @@ namespace Tango.BL.DTO { public class SegmentDTO : SegmentDTOBase { + public List BrushStops { get; set; } + public SegmentDTO() + { + BrushStops = new List(); + } } } diff --git a/Software/Visual_Studio/Tango.BL/Entities/Job.cs b/Software/Visual_Studio/Tango.BL/Entities/Job.cs index 19f374951..d2a416271 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/Job.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/Job.cs @@ -335,6 +335,7 @@ namespace Tango.BL.Entities cloned.Name = Name + " - Copy"; cloned.CreationDate = DateTime.UtcNow; + cloned.IsSynchronized = false; cloned.LastRun = null; cloned.ColorSpace = ColorSpace; cloned.Customer = Customer; diff --git a/Software/Visual_Studio/Tango.BL/Entities/JobBase.cs b/Software/Visual_Studio/Tango.BL/Entities/JobBase.cs index b356ecbfe..599e379a8 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/JobBase.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/JobBase.cs @@ -81,6 +81,8 @@ namespace Tango.BL.Entities public event EventHandler LengthPercentageFactorChanged; + public event EventHandler IsSynchronizedChanged; + public event EventHandler ColorCatalogChanged; public event EventHandler ColorSpaceChanged; @@ -993,6 +995,33 @@ namespace Tango.BL.Entities } } + protected Boolean _issynchronized; + + /// + /// Gets or sets the jobbase is synchronized. + /// + + [Column("IS_SYNCHRONIZED")] + + public Boolean IsSynchronized + { + get + { + return _issynchronized; + } + + set + { + if (_issynchronized != value) + { + _issynchronized = value; + + OnIsSynchronizedChanged(value); + + } + } + } + protected ColorCatalog _colorcatalog; /// @@ -1499,6 +1528,15 @@ namespace Tango.BL.Entities RaisePropertyChanged(nameof(LengthPercentageFactor)); } + /// + /// Called when the IsSynchronized has changed. + /// + protected virtual void OnIsSynchronizedChanged(Boolean issynchronized) + { + IsSynchronizedChanged?.Invoke(this, issynchronized); + RaisePropertyChanged(nameof(IsSynchronized)); + } + /// /// Called when the ColorCatalog has changed. /// diff --git a/Software/Visual_Studio/Tango.BL/Entities/JobRunBase.cs b/Software/Visual_Studio/Tango.BL/Entities/JobRunBase.cs index 16351179f..c90aa5eab 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/JobRunBase.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/JobRunBase.cs @@ -41,6 +41,8 @@ namespace Tango.BL.Entities public event EventHandler FailedMessageChanged; + public event EventHandler IsSynchronizedChanged; + protected String _machineguid; /// @@ -228,6 +230,33 @@ namespace Tango.BL.Entities } } + protected Boolean _issynchronized; + + /// + /// Gets or sets the jobrunbase is synchronized. + /// + + [Column("IS_SYNCHRONIZED")] + + public Boolean IsSynchronized + { + get + { + return _issynchronized; + } + + set + { + if (_issynchronized != value) + { + _issynchronized = value; + + OnIsSynchronizedChanged(value); + + } + } + } + /// /// Called when the StartDate has changed. /// @@ -273,6 +302,15 @@ namespace Tango.BL.Entities RaisePropertyChanged(nameof(FailedMessage)); } + /// + /// Called when the IsSynchronized has changed. + /// + protected virtual void OnIsSynchronizedChanged(Boolean issynchronized) + { + IsSynchronizedChanged?.Invoke(this, issynchronized); + RaisePropertyChanged(nameof(IsSynchronized)); + } + /// /// Initializes a new instance of the class. /// diff --git a/Software/Visual_Studio/Tango.BL/Entities/MachinesEventBase.cs b/Software/Visual_Studio/Tango.BL/Entities/MachinesEventBase.cs index 5091267e8..0a3377dce 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/MachinesEventBase.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/MachinesEventBase.cs @@ -32,6 +32,8 @@ namespace Tango.BL.Entities public event EventHandler DescriptionChanged; + public event EventHandler IsSynchronizedChanged; + public event EventHandler EventTypeChanged; public event EventHandler MachineChanged; @@ -197,6 +199,33 @@ namespace Tango.BL.Entities } } + protected Boolean _issynchronized; + + /// + /// Gets or sets the machineseventbase is synchronized. + /// + + [Column("IS_SYNCHRONIZED")] + + public Boolean IsSynchronized + { + get + { + return _issynchronized; + } + + set + { + if (_issynchronized != value) + { + _issynchronized = value; + + OnIsSynchronizedChanged(value); + + } + } + } + protected EventType _eventtype; /// @@ -320,6 +349,15 @@ namespace Tango.BL.Entities RaisePropertyChanged(nameof(Description)); } + /// + /// Called when the IsSynchronized has changed. + /// + protected virtual void OnIsSynchronizedChanged(Boolean issynchronized) + { + IsSynchronizedChanged?.Invoke(this, issynchronized); + RaisePropertyChanged(nameof(IsSynchronized)); + } + /// /// Called when the EventType has changed. /// diff --git a/Software/Visual_Studio/Tango.BL/Entities/TangoUpdate.cs b/Software/Visual_Studio/Tango.BL/Entities/TangoUpdate.cs index 5c254a6a9..4ab67b7c5 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/TangoUpdate.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/TangoUpdate.cs @@ -65,6 +65,19 @@ namespace Tango.BL.Entities } } + [NotMapped] + [JsonIgnore] + public bool IsSynchronization + { + get + { + return + UpdateStatus == TangoUpdateStatuses.SynchronizationStarted || + UpdateStatus == TangoUpdateStatuses.SynchronizationCompleted || + UpdateStatus == TangoUpdateStatuses.SynchronizationFailed; + } + } + [NotMapped] [JsonIgnore] public bool IsStarted @@ -74,7 +87,8 @@ namespace Tango.BL.Entities return UpdateStatus == TangoUpdateStatuses.SetupStarted || UpdateStatus == TangoUpdateStatuses.UpdateStarted || - UpdateStatus == TangoUpdateStatuses.DatabaseStarted; + UpdateStatus == TangoUpdateStatuses.DatabaseStarted || + UpdateStatus == TangoUpdateStatuses.SynchronizationStarted; } } @@ -87,7 +101,8 @@ namespace Tango.BL.Entities return UpdateStatus == TangoUpdateStatuses.SetupCompleted || UpdateStatus == TangoUpdateStatuses.UpdateCompleted || - UpdateStatus == TangoUpdateStatuses.DatabaseCompleted; + UpdateStatus == TangoUpdateStatuses.DatabaseCompleted || + UpdateStatus == TangoUpdateStatuses.SynchronizationCompleted; } } @@ -100,7 +115,8 @@ namespace Tango.BL.Entities return UpdateStatus == TangoUpdateStatuses.SetupFailed || UpdateStatus == TangoUpdateStatuses.UpdateFailed || - UpdateStatus == TangoUpdateStatuses.DatabaseFailed; + UpdateStatus == TangoUpdateStatuses.DatabaseFailed || + UpdateStatus == TangoUpdateStatuses.SynchronizationFailed; } } diff --git a/Software/Visual_Studio/Tango.BL/Enumerations/TangoUpdateStatuses.cs b/Software/Visual_Studio/Tango.BL/Enumerations/TangoUpdateStatuses.cs index 30d324317..855d8b29b 100644 --- a/Software/Visual_Studio/Tango.BL/Enumerations/TangoUpdateStatuses.cs +++ b/Software/Visual_Studio/Tango.BL/Enumerations/TangoUpdateStatuses.cs @@ -16,7 +16,7 @@ namespace Tango.BL.Enumerations [Description("Setup failed")] SetupFailed = 2, - [Description("Software updated started but did not complete")] + [Description("Software update started but did not complete")] UpdateStarted = 100, [Description("Software update completed successfully")] UpdateCompleted = 101, @@ -29,5 +29,12 @@ namespace Tango.BL.Enumerations DatabaseCompleted = 201, [Description("Database update failed")] DatabaseFailed = 202, + + [Description("Synchronization started but did not complete")] + SynchronizationStarted = 300, + [Description("Synchronization completed successfully")] + SynchronizationCompleted = 301, + [Description("Synchronization failed")] + SynchronizationFailed = 302, } } diff --git a/Software/Visual_Studio/Tango.BL/IObservableEntity.cs b/Software/Visual_Studio/Tango.BL/IObservableEntity.cs index 244486add..96a150b4a 100644 --- a/Software/Visual_Studio/Tango.BL/IObservableEntity.cs +++ b/Software/Visual_Studio/Tango.BL/IObservableEntity.cs @@ -90,5 +90,10 @@ namespace Tango.BL /// /// The context. void Delete(ObservablesContext context); + + /// + /// Called when before entity is saved by the context. + /// + void OnBeforeSave(); } } diff --git a/Software/Visual_Studio/Tango.BL/ObservableEntity.cs b/Software/Visual_Studio/Tango.BL/ObservableEntity.cs index 982b853f9..e9bb711da 100644 --- a/Software/Visual_Studio/Tango.BL/ObservableEntity.cs +++ b/Software/Visual_Studio/Tango.BL/ObservableEntity.cs @@ -620,6 +620,18 @@ namespace Tango.BL #endregion + #region Virtual Methods + + /// + /// Called when before entity is saved by the context. + /// + public virtual void OnBeforeSave() + { + + } + + #endregion + #region INotify Property Changed /// diff --git a/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs b/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs index b7559cdc3..263574f68 100644 --- a/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs +++ b/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data.Entity; +using System.Data.Entity.Core.Objects; using System.Data.Entity.Infrastructure; using System.Data.SQLite; using System.IO; @@ -35,7 +36,7 @@ namespace Tango.BL /// public ObservablesContext() { - + } /// @@ -102,6 +103,15 @@ namespace Tango.BL return CreateDefault(address, "Tango", DataSourceType.SQLServer); } + /// + /// Gets the inner object context. + /// + /// + private ObjectContext GetObjectContext() + { + return ((IObjectContextAdapter)this).ObjectContext; + } + /// /// Saves all changes made in this context to the underlying database. /// @@ -110,6 +120,14 @@ namespace Tango.BL /// public override int SaveChanges() { + foreach (var entity in ChangeTracker.Entries().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified).ToList()) + { + if (entity is IObservableEntity && entity != null) + { + (entity as IObservableEntity).OnBeforeSave(); + } + } + var result = base.SaveChanges(); RaisePendingNotifications(); return result; @@ -129,6 +147,14 @@ namespace Tango.BL /// public override Task SaveChangesAsync(CancellationToken cancellationToken) { + foreach (var entity in ChangeTracker.Entries().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified).ToList().Select(x => x.Entity).ToList()) + { + if (entity is IObservableEntity && entity != null) + { + (entity as IObservableEntity).OnBeforeSave(); + } + } + var result = base.SaveChangesAsync(cancellationToken); RaisePendingNotifications(); return result; @@ -168,9 +194,6 @@ namespace Tango.BL { IObservableEntity modified = entityEntry.Entity as IObservableEntity; - //Good chance to update "LAST_UPDATED" field! - modified.LastUpdated = DateTime.UtcNow; - foreach (var toNotify in ObservableEntitiesContainer.RegisteredEntities.ToList().Where(x => x.Guid == modified.Guid).ToList()) { _pending_notifications.Add(new ObservableModifiedEventArgs(this, modified, toNotify)); diff --git a/Software/Visual_Studio/Tango.CodeGeneration/Templates/TangoWebClientCodeFile.cshtml b/Software/Visual_Studio/Tango.CodeGeneration/Templates/TangoWebClientCodeFile.cshtml index 7d9ebc075..3918ce928 100644 --- a/Software/Visual_Studio/Tango.CodeGeneration/Templates/TangoWebClientCodeFile.cshtml +++ b/Software/Visual_Studio/Tango.CodeGeneration/Templates/TangoWebClientCodeFile.cshtml @@ -42,6 +42,15 @@ namespace @(model.Namespace) } + /// + /// Initializes a new instance of the class. + /// + /// Other instance. + public @(model.Name)(@(model.Name) cloned) : base(cloned) + { + + } + @foreach (var action in model.Actions) {
diff --git a/Software/Visual_Studio/Tango.Core/ExtensionMethods/ExceptionExtensions.cs b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ExceptionExtensions.cs index af4fc39b5..7b87245b7 100644 --- a/Software/Visual_Studio/Tango.Core/ExtensionMethods/ExceptionExtensions.cs +++ b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ExceptionExtensions.cs @@ -30,6 +30,23 @@ public static class ExceptionExtensions return stringBuilder.ToString(); } + /// + /// Gets the first exception if this is an aggregated exception. + /// + /// The exception. + /// + public static Exception GetFirstIfAggregate(this Exception exception) + { + var ex = exception as AggregateException; + + if (ex != null && ex.InnerExceptions.Count > 0) + { + return ex.InnerExceptions.First(); + } + + return exception; + } + /// /// Flattens the exception message in case it is an aggregated exception. /// diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs index 17ec544c0..923cceacf 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs @@ -56,6 +56,7 @@ namespace Tango.DAL.Remote.DB public Nullable SAMPLE_DYE_APPROVE_DATE { get; set; } public int EDITING_STATE { get; set; } public double LENGTH_PERCENTAGE_FACTOR { get; set; } + public bool IS_SYNCHRONIZED { get; set; } public virtual COLOR_CATALOGS COLOR_CATALOGS { get; set; } public virtual COLOR_SPACES COLOR_SPACES { get; set; } diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB_RUNS.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB_RUNS.cs index 24f61f03c..186c82727 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB_RUNS.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB_RUNS.cs @@ -24,5 +24,6 @@ namespace Tango.DAL.Remote.DB public int STATUS { get; set; } public double END_POSITION { get; set; } public string FAILED_MESSAGE { get; set; } + public bool IS_SYNCHRONIZED { get; set; } } } diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/MACHINES_EVENTS.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/MACHINES_EVENTS.cs index d83f123a2..c555a1ce3 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/MACHINES_EVENTS.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/MACHINES_EVENTS.cs @@ -23,6 +23,7 @@ namespace Tango.DAL.Remote.DB public string USER_GUID { get; set; } public System.DateTime DATE_TIME { get; set; } public string DESCRIPTION { get; set; } + public bool IS_SYNCHRONIZED { get; set; } public virtual EVENT_TYPES EVENT_TYPES { get; set; } public virtual MACHINE MACHINE { get; set; } diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx index 8c8b66a5c..1a27648e2 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx @@ -593,6 +593,7 @@ + @@ -634,6 +635,7 @@ + @@ -745,6 +747,7 @@ + @@ -3648,6 +3651,7 @@ + @@ -3689,6 +3693,7 @@ + @@ -3828,6 +3833,7 @@ + @@ -5924,6 +5930,7 @@ + @@ -5940,6 +5947,7 @@ + @@ -6085,6 +6093,7 @@ + diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram index 2feb68642..a3618fb5f 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram @@ -5,80 +5,80 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/Tango.Settings/SettingsManager.cs b/Software/Visual_Studio/Tango.Settings/SettingsManager.cs index 88a3f59e1..d106ebaca 100644 --- a/Software/Visual_Studio/Tango.Settings/SettingsManager.cs +++ b/Software/Visual_Studio/Tango.Settings/SettingsManager.cs @@ -93,7 +93,6 @@ namespace Tango.Settings { try { - _logManager.Log("Retrieving settings for " + typeof(T).Name); EnsureLoaded(); } catch (Exception ex) diff --git a/Software/Visual_Studio/Tango.Transport/Web/WebTransportClient.cs b/Software/Visual_Studio/Tango.Transport/Web/WebTransportClient.cs index ed2e69468..e838a6a05 100644 --- a/Software/Visual_Studio/Tango.Transport/Web/WebTransportClient.cs +++ b/Software/Visual_Studio/Tango.Transport/Web/WebTransportClient.cs @@ -21,6 +21,12 @@ namespace Tango.Transport.Web public string AuthenticationToken { get; set; } + public TimeSpan RequestTimeout + { + get { return _httpClient.Timeout; } + set { _httpClient.Timeout = value; } + } + static WebTransportClient() { _settings = new JsonSerializerSettings() @@ -109,6 +115,7 @@ namespace Tango.Transport.Web if (type != null) { exception = Activator.CreateInstance(type, new object[] { exceptionMessage + "\n" + stackTrace }) as Exception; + } else { diff --git a/Software/Visual_Studio/Tango.Web/Controllers/TangoController.cs b/Software/Visual_Studio/Tango.Web/Controllers/TangoController.cs index d82fcb5f2..3fd3d469e 100644 --- a/Software/Visual_Studio/Tango.Web/Controllers/TangoController.cs +++ b/Software/Visual_Studio/Tango.Web/Controllers/TangoController.cs @@ -70,7 +70,7 @@ namespace Tango.Web.Controllers code = HttpStatusCode.Unauthorized; } - var httpException = new HttpResponseException(Request.CreateErrorResponse(code, ex.FlattenMessage())); + var httpException = new HttpResponseException(Request.CreateErrorResponse(code, ex.FlattenMessage(), ex)); #if DEBUG throw httpException; diff --git a/Software/Visual_Studio/Tango.Web/TangoWebClient.cs b/Software/Visual_Studio/Tango.Web/TangoWebClient.cs index 1d2f9fc8e..7c3c6ad2a 100644 --- a/Software/Visual_Studio/Tango.Web/TangoWebClient.cs +++ b/Software/Visual_Studio/Tango.Web/TangoWebClient.cs @@ -37,6 +37,12 @@ namespace Tango.Web public WebToken WebToken { get; private set; } public bool IsAuthenticated { get; private set; } + public TimeSpan RequestTimeout + { + get { return _client.RequestTimeout; } + set { _client.RequestTimeout = value; } + } + public TangoWebClient(DeploymentSlot environment, String controller) { _client = new WebTransportClient(); @@ -57,6 +63,24 @@ namespace Tango.Web Token = token; } + public TangoWebClient(TangoWebClient cloned) + { + _client = new WebTransportClient(); + Environment = cloned.Environment; + Address = cloned.Address; + Controller = cloned.Controller; + IsAuthenticated = cloned.IsAuthenticated; + RequestTimeout = cloned.RequestTimeout; + WebToken = cloned.WebToken; + _lastLoginRequest = cloned._lastLoginRequest; + Token = cloned.Token; + } + + public T Clone() where T : TangoWebClient + { + return Activator.CreateInstance(typeof(T), new object[] { this }) as T; + } + public async Task Login(TLoginRequest request) { var response = await _client.PostJson(GetActionAddress("Login"), request); @@ -85,7 +109,7 @@ namespace Tango.Web var response = await _client.PostJson(GetActionAddress(action), request); return response; } - catch (TokenExpiredException) + catch (TokenExpiredException ex) { try { @@ -98,7 +122,7 @@ namespace Tango.Web throw; } } - catch + catch (Exception ex) { throw; } diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln index 8dc160543..b089332d6 100644 --- a/Software/Visual_Studio/Tango.sln +++ b/Software/Visual_Studio/Tango.sln @@ -325,6 +325,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.PPC.Packages.SamplePr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.PPC.Packages.SamplePostPackage", "PPC\UpdatePackages\Tango.PPC.Packages.SamplePostPackage\Tango.PPC.Packages.SamplePostPackage.csproj", "{DA391B02-AE28-4EA1-A80F-D0F4C8029FFA}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.PPC.SchemaSynchronizer.CLI", "PPC\Tango.PPC.SchemaSynchronizer.CLI\Tango.PPC.SchemaSynchronizer.CLI.csproj", "{F3746F2B-E4AE-498B-9D42-74F95D992460}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AppVeyor|Any CPU = AppVeyor|Any CPU @@ -5777,6 +5779,46 @@ Global {DA391B02-AE28-4EA1-A80F-D0F4C8029FFA}.Release|x64.Build.0 = Release|Any CPU {DA391B02-AE28-4EA1-A80F-D0F4C8029FFA}.Release|x86.ActiveCfg = Release|Any CPU {DA391B02-AE28-4EA1-A80F-D0F4C8029FFA}.Release|x86.Build.0 = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.AppVeyor|Any CPU.ActiveCfg = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.AppVeyor|Any CPU.Build.0 = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.AppVeyor|ARM.ActiveCfg = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.AppVeyor|ARM.Build.0 = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.AppVeyor|ARM64.ActiveCfg = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.AppVeyor|ARM64.Build.0 = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.AppVeyor|x64.ActiveCfg = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.AppVeyor|x64.Build.0 = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.AppVeyor|x86.ActiveCfg = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.AppVeyor|x86.Build.0 = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Debug|ARM.ActiveCfg = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Debug|ARM.Build.0 = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Debug|ARM64.Build.0 = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Debug|x64.ActiveCfg = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Debug|x64.Build.0 = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Debug|x86.ActiveCfg = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Debug|x86.Build.0 = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.DefaultBuild|Any CPU.ActiveCfg = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.DefaultBuild|Any CPU.Build.0 = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.DefaultBuild|ARM.ActiveCfg = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.DefaultBuild|ARM.Build.0 = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.DefaultBuild|ARM64.ActiveCfg = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.DefaultBuild|ARM64.Build.0 = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.DefaultBuild|x64.ActiveCfg = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.DefaultBuild|x64.Build.0 = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.DefaultBuild|x86.ActiveCfg = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.DefaultBuild|x86.Build.0 = Debug|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Release|Any CPU.Build.0 = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Release|ARM.ActiveCfg = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Release|ARM.Build.0 = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Release|ARM64.ActiveCfg = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Release|ARM64.Build.0 = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Release|x64.ActiveCfg = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Release|x64.Build.0 = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Release|x86.ActiveCfg = Release|Any CPU + {F3746F2B-E4AE-498B-9D42-74F95D992460}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -5884,6 +5926,7 @@ Global {D74893F2-9E39-4C72-BDD4-937404E1FC37} = {5F6BBAA8-EAD0-4B18-97E5-55B4F56DD760} {2CD12594-3522-4658-A65F-190EE58B6AFA} = {E728CBD9-1AF4-4814-A218-E4BD26E7EDEA} {DA391B02-AE28-4EA1-A80F-D0F4C8029FFA} = {E728CBD9-1AF4-4814-A218-E4BD26E7EDEA} + {F3746F2B-E4AE-498B-9D42-74F95D992460} = {C81ED1A3-D18C-4D80-A8F5-061994A14A60} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution BuildVersion_UseGlobalSettings = False diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs index 378fc3eea..da5ce16f7 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs @@ -285,7 +285,16 @@ namespace Tango.MachineService.Controllers [HttpPost] public LoginResponse Login(LoginRequest request) { - var authResult = _ad_manager.ValidateUserCredentials(request.Email, request.Password); + AuthenticationResult authResult = null; + + try + { + authResult = _ad_manager.ValidateUserCredentials(request.Email, request.Password); + } + catch (Exception ex) + { + throw new AuthenticationException(ex.FlattenMessage()); + } if (!_ad_manager.CanUserAccessCurrentEnvironment(request.Email)) { diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs index 0d9a2993b..b2a1da980 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs @@ -398,12 +398,9 @@ namespace Tango.MachineService.Controllers Type = DataSourceType.SQLServer, }; - var machine_version = db.MachineVersions.SingleOrDefault(x => x.Guid == machine.MachineVersionGuid); - var latest_machine_version = db.TangoVersions.Where(x => x.MachineVersionGuid == machine_version.Guid).ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); - TangoUpdate tangoUpdate = new TangoUpdate(); - tangoUpdate.ApplicationVersion = latest_machine_version.Version; - tangoUpdate.FirmwareVersion = latest_machine_version.FirmwareVersion; + tangoUpdate.ApplicationVersion = request.ApplicationVersion; + tangoUpdate.FirmwareVersion = request.FirmwareVersion; tangoUpdate.MachineGuid = machine.Guid; tangoUpdate.StartDate = DateTime.UtcNow; tangoUpdate.UpdateStatus = TangoUpdateStatuses.DatabaseStarted; @@ -423,6 +420,276 @@ namespace Tango.MachineService.Controllers #endregion + #region Synchronization + + [HttpPost] + [JwtTokenFilter] + public UploadMachineDataResponse UploadMachineData(UploadMachineDataRequest request) + { + UploadMachineDataResponse response = new UploadMachineDataResponse(); + response.NotifyCompletedToken = Guid.NewGuid().ToString(); + + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + var machine = db.Machines.SingleOrDefault(x => x.Guid == RequestToken.Object.MachineGuid); + + if (machine == null) + { + throw new AuthenticationException("The specified machine could not be found."); + } + + TangoUpdate tangoUpdate = new TangoUpdate(); + tangoUpdate.ApplicationVersion = request.ApplicationVersion; + tangoUpdate.FirmwareVersion = request.FirmwareVersion; + tangoUpdate.MachineGuid = machine.Guid; + tangoUpdate.StartDate = DateTime.UtcNow; + tangoUpdate.UpdateStatus = TangoUpdateStatuses.SynchronizationStarted; + db.TangoUpdates.Add(tangoUpdate); + db.SaveChanges(); + + _pendingUpdates.Add(new PPCPendingUpdate() + { + Token = response.NotifyCompletedToken, + TangoUpdateGuid = tangoUpdate.Guid, + }); + } + + User machineUser = null; + + try + { + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + var machine = db.Machines.SingleOrDefault(x => x.Guid == RequestToken.Object.MachineGuid); + + if (machine == null) + { + throw new AuthenticationException("The specified machine could not be found."); + } + + machineUser = db.Users.Include(x => x.Contact).SingleOrDefault(x => x.Contact.FirstName == machine.Name); + + if (machineUser == null) + { + //No machine user then create one. + machineUser = new User(); + machineUser.Email = machine.SerialNumber + "@twine-s.com"; + machineUser.Password = machine.SerialNumber; + machineUser.OrganizationGuid = machine.OrganizationGuid; + machineUser.Contact = new Contact(); + machineUser.Contact.Email = machineUser.Email; + machineUser.Contact.FirstName = machine.Name; + machineUser.Contact.LastName = machine.Name; + machineUser.Contact.FullName = machine.Name; + machineUser.Address = new Address(); + + db.Users.Add(machineUser); + db.SaveChanges(); + } + } + + //Insert/Replace Jobs. + foreach (var dto in request.Jobs) + { + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + try + { + var job = dto.ToObservable(); + + job.ID = 0; + job.UserGuid = machineUser.Guid; + job.CustomerGuid = null; + job.IsSynchronized = true; + + var existingJob = db.Jobs.SingleOrDefault(x => x.Guid == job.Guid); + + if (existingJob == null) + { + db.Jobs.Add(job); + db.SaveChanges(); + } + else if (job.LastUpdated > existingJob.LastUpdated) + { + existingJob.Delete(db); + db.Jobs.Add(job); + db.SaveChanges(); + } + } + catch (Exception ex) + { + response.FailedJobs.Add(new SynchronizationFailedEntity() + { + Guid = dto.Guid, + Reason = ex.FlattenMessage(), + }); + } + } + } + + //Insert JobRuns. + foreach (var dto in request.JobRuns) + { + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + try + { + var run = dto.ToObservable(); + run.ID = 0; + run.IsSynchronized = true; + + if (db.JobRuns.SingleOrDefault(x => x.Guid == run.Guid) == null) + { + db.JobRuns.Add(run); + db.SaveChanges(); + } + } + catch (Exception ex) + { + response.FailedJobRuns.Add(new SynchronizationFailedEntity() + { + Guid = dto.Guid, + Reason = ex.FlattenMessage(), + }); + } + } + } + + //Insert MachineEvents. + foreach (var dto in request.MachineEvents) + { + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + try + { + var ev = dto.ToObservable(); + ev.ID = 0; + ev.UserGuid = machineUser.Guid; + ev.IsSynchronized = true; + + if (db.MachinesEvents.SingleOrDefault(x => x.Guid == ev.Guid) == null) + { + db.MachinesEvents.Add(ev); + db.SaveChanges(); + } + } + catch (Exception ex) + { + response.FailedMachineEvents.Add(new SynchronizationFailedEntity() + { + Guid = dto.Guid, + Reason = ex.FlattenMessage(), + }); + } + } + } + } + catch (Exception ex) + { + NotifyUpdateCompleted(new MachineUpdateCompletedRequest() + { + Status = TangoUpdateStatuses.SynchronizationFailed, + FailedReason = ex.FlattenMessage(), + FailedLog = ex.FlattenException(), + Token = response.NotifyCompletedToken, + }); + throw ex; + } + + return response; + } + + [HttpPost] + [JwtTokenFilter] + public DownloadMachineDataResponse DownloadMachineData(DownloadMachineDataRequest request) + { + DownloadMachineDataResponse response = new DownloadMachineDataResponse(); + + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + var machine = db.Machines.SingleOrDefault(x => x.Guid == RequestToken.Object.MachineGuid); + + if (machine == null) + { + throw new AuthenticationException("The specified machine could not be found."); + } + + //Send Jobs + if (request.RequestJobs) + { + var jobs = new JobsCollectionBuilder(db).Set(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).WithSegments().WithBrushStops().Query(x => x.Take(request.MaxJobs).OrderByDescending(z => z.LastUpdated)).BuildList(); + + foreach (var job in jobs) + { + JobDTO dto = JobDTO.FromObservable(job); + response.Jobs.Add(dto); + } + } + + //Send Job Runs + if (request.RequestJobRuns) + { + var jobRuns = db.JobRuns.Where(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).Take(request.MaxJobRuns).OrderByDescending(x => x.LastUpdated).ToList(); + + foreach (var jobRun in jobRuns) + { + JobRunDTO dto = JobRunDTO.FromObservable(jobRun); + response.JobRuns.Add(dto); + } + } + + //Send Machine Events + if (request.RequestMachineEvents) + { + var machineEvents = db.MachinesEvents.Where(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).Take(request.MaxMachinesEvents).OrderByDescending(x => x.LastUpdated).ToList(); + + foreach (var machineEvent in machineEvents) + { + MachinesEventDTO dto = MachinesEventDTO.FromObservable(machineEvent); + response.MachineEvents.Add(dto); + } + } + } + + return response; + } + + [HttpPost] + [JwtTokenFilter] + public NotifyMachineDataDownloadCompletedResponse NotifyMachineDataDownloadCompleted(NotifyMachineDataDownloadCompletedRequest request) + { + var response = new NotifyMachineDataDownloadCompletedResponse(); + + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + var machine = db.Machines.SingleOrDefault(x => x.Guid == RequestToken.Object.MachineGuid); + + if (machine == null) + { + throw new AuthenticationException("The specified machine could not be found."); + } + + if (request.SynchronizedJobs.Count > 0) + { + db.Database.ExecuteSqlCommand($"UPDATE JOBS SET IS_SYNCHRONIZED = 1 WHERE GUID IN ({String.Join(",", request.SynchronizedJobs.Select(x => "'" + x + "'"))});"); + } + + if (request.SynchronizedJobRuns.Count > 0) + { + db.Database.ExecuteSqlCommand($"UPDATE JOB_RUNS SET IS_SYNCHRONIZED = 1 WHERE GUID IN ({String.Join(",", request.SynchronizedJobRuns.Select(x => "'" + x + "'"))});"); + } + + if (request.SynchronizedMachineEvents.Count > 0) + { + db.Database.ExecuteSqlCommand($"UPDATE MACHINES_EVENTS SET IS_SYNCHRONIZED = 1 WHERE GUID IN ({String.Join(",", request.SynchronizedMachineEvents.Select(x => "'" + x + "'"))});"); + } + } + + return response; + } + + #endregion + #region Version Upload [HttpPost] diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Web.config b/Software/Visual_Studio/Web/Tango.MachineService/Web.config index 97a0d511f..658439cc0 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Web.config +++ b/Software/Visual_Studio/Web/Tango.MachineService/Web.config @@ -25,7 +25,7 @@ - + @@ -62,6 +62,11 @@ + + + + + -- cgit v1.3.1 From f1ef8138154ade048b7e2ff0aac31db5594d26b9 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Fri, 13 Dec 2019 13:02:08 +0200 Subject: Modified DIalogVieVM to allow OK with CanClose = false. --- Software/DB/PPC/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/PPC/Tango_log.ldf | Bin 53673984 -> 53673984 bytes .../ViewModels/FirmwareUpgradeViewVM.cs | 5 +++++ .../PPC/Tango.PPC.UI/Dialogs/PowerUpViewVM.cs | 1 + .../Visual_Studio/Tango.SharedUI/DialogViewVM.cs | 2 +- 5 files changed, 7 insertions(+), 1 deletion(-) (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/DB/PPC/Tango.mdf b/Software/DB/PPC/Tango.mdf index a24738a12..35dde42f3 100644 Binary files a/Software/DB/PPC/Tango.mdf and b/Software/DB/PPC/Tango.mdf differ diff --git a/Software/DB/PPC/Tango_log.ldf b/Software/DB/PPC/Tango_log.ldf index d548ec168..60f6da390 100644 Binary files a/Software/DB/PPC/Tango_log.ldf and b/Software/DB/PPC/Tango_log.ldf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/FirmwareUpgradeViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/FirmwareUpgradeViewVM.cs index e45c29f73..365c1db49 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/FirmwareUpgradeViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/FirmwareUpgradeViewVM.cs @@ -207,6 +207,11 @@ namespace Tango.MachineStudio.UI.ViewModels } } + protected override bool CanOK() + { + return base.CanOK() && CanClose; + } + private async void AbortUpgrade() { CanClose = true; diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpViewVM.cs index c0ef85bcc..22e489ffa 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpViewVM.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpViewVM.cs @@ -84,6 +84,7 @@ namespace Tango.PPC.UI.Dialogs public PowerUpViewVM() { RemainingSeconds = 20; + CanClose = false; IsMinimalTemperature = true; IsTimeoutEnabled = true; _timer = new Timer(); diff --git a/Software/Visual_Studio/Tango.SharedUI/DialogViewVM.cs b/Software/Visual_Studio/Tango.SharedUI/DialogViewVM.cs index f740eab84..bf75fd6ef 100644 --- a/Software/Visual_Studio/Tango.SharedUI/DialogViewVM.cs +++ b/Software/Visual_Studio/Tango.SharedUI/DialogViewVM.cs @@ -24,7 +24,7 @@ namespace Tango.SharedUI { CanClose = true; CloseCommand = new RelayCommand(Cancel, (x) => CanClose); - OKCommand = new RelayCommand(Accept, (x) => CanClose && CanOK()); + OKCommand = new RelayCommand(Accept, (x) => CanOK()); } private bool _canClose; -- cgit v1.3.1 From ab518a645fed89633aeb67ad107afffe3567499b Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Fri, 13 Dec 2019 14:52:38 +0200 Subject: Added sites and machine studio module template. --- Software/DB/TCC/TCC.mdf | Bin 8388608 -> 8388608 bytes Software/DB/TCC/TCC_log.ldf | Bin 8388608 -> 8388608 bytes Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 22675456 -> 22675456 bytes .../Tango.MachineStudio.Sites/Images/site.png | Bin 0 -> 22073 bytes .../Properties/AssemblyInfo.cs | 19 +++ .../Properties/Resources.Designer.cs | 62 +++++++++ .../Properties/Resources.resx | 117 ++++++++++++++++ .../Properties/Settings.Designer.cs | 30 ++++ .../Properties/Settings.settings | 7 + .../Tango.MachineStudio.Sites/SitesModule.cs | 62 +++++++++ .../Tango.MachineStudio.Sites.csproj | 147 ++++++++++++++++++++ .../Tango.MachineStudio.Sites/ViewModelLocator.cs | 29 ++++ .../ViewModels/MainViewVM.cs | 18 +++ .../Tango.MachineStudio.Sites/Views/MainView.xaml | 15 ++ .../Views/MainView.xaml.cs | 28 ++++ .../Modules/Tango.MachineStudio.Sites/app.config | 75 ++++++++++ .../Tango.MachineStudio.Sites/packages.config | 8 ++ .../Tango.MachineStudio.UI.csproj | 6 +- .../Project Templates/Machine Studio Module.zip | Bin 0 -> 17805 bytes .../Visual_Studio/Tango.BL/DTO/MachineDTOBase.cs | 8 ++ .../Visual_Studio/Tango.BL/DTO/MachinesRmlDTO.cs | 14 -- .../Tango.BL/DTO/MachinesRmlDTOBase.cs | 41 ------ .../Tango.BL/DTO/OrganizationsRmlDTO.cs | 14 -- .../Tango.BL/DTO/OrganizationsRmlDTOBase.cs | 41 ------ Software/Visual_Studio/Tango.BL/DTO/SiteDTO.cs | 14 ++ Software/Visual_Studio/Tango.BL/DTO/SiteDTOBase.cs | 49 +++++++ Software/Visual_Studio/Tango.BL/DTO/SitesRmlDTO.cs | 14 ++ .../Visual_Studio/Tango.BL/DTO/SitesRmlDTOBase.cs | 41 ++++++ .../Tango.BL/Entities/HardwareBlowerBase.cs | 2 + .../Visual_Studio/Tango.BL/Entities/MachineBase.cs | 25 ++++ .../Visual_Studio/Tango.BL/Entities/MachinesRml.cs | 12 -- .../Tango.BL/Entities/MachinesRmlBase.cs | 86 ------------ .../Tango.BL/Entities/OrganizationsRml.cs | 12 -- .../Tango.BL/Entities/OrganizationsRmlBase.cs | 86 ------------ Software/Visual_Studio/Tango.BL/Entities/Site.cs | 12 ++ .../Visual_Studio/Tango.BL/Entities/SiteBase.cs | 137 +++++++++++++++++++ .../Visual_Studio/Tango.BL/Entities/SitesRml.cs | 12 ++ .../Tango.BL/Entities/SitesRmlBase.cs | 86 ++++++++++++ .../Visual_Studio/Tango.BL/ObservablesContext.cs | 32 ++--- .../ObservablesEntitiesAdapterExtension.cs | 152 ++++++++++----------- .../ObservablesStaticCollectionsExtension.cs | 152 ++++++++++----------- Software/Visual_Studio/Tango.BL/Tango.BL.csproj | 16 +-- .../Visual_Studio/Tango.DAL.Remote/DB/MACHINE.cs | 1 + .../Tango.DAL.Remote/DB/MACHINES_RMLS.cs | 23 ---- .../Tango.DAL.Remote/DB/ORGANIZATIONS_RMLS.cs | 23 ---- .../Tango.DAL.Remote/DB/RemoteADO.Context.cs | 4 +- .../Tango.DAL.Remote/DB/RemoteADO.edmx | 138 ++++++++++--------- .../Tango.DAL.Remote/DB/RemoteADO.edmx.diagram | 152 ++++++++++----------- Software/Visual_Studio/Tango.DAL.Remote/DB/SITE.cs | 24 ++++ .../Tango.DAL.Remote/DB/SITES_RMLS.cs | 23 ++++ .../Tango.DAL.Remote/Tango.DAL.Remote.csproj | 12 +- Software/Visual_Studio/Tango.sln | 43 ++++++ 53 files changed, 1445 insertions(+), 679 deletions(-) create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Images/site.png create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/AssemblyInfo.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Resources.Designer.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Resources.resx create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Settings.Designer.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Settings.settings create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/SitesModule.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Tango.MachineStudio.Sites.csproj create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/ViewModelLocator.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/ViewModels/MainViewVM.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Views/MainView.xaml create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Views/MainView.xaml.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/app.config create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/packages.config create mode 100644 Software/Visual_Studio/Project Templates/Machine Studio Module.zip delete mode 100644 Software/Visual_Studio/Tango.BL/DTO/MachinesRmlDTO.cs delete mode 100644 Software/Visual_Studio/Tango.BL/DTO/MachinesRmlDTOBase.cs delete mode 100644 Software/Visual_Studio/Tango.BL/DTO/OrganizationsRmlDTO.cs delete mode 100644 Software/Visual_Studio/Tango.BL/DTO/OrganizationsRmlDTOBase.cs create mode 100644 Software/Visual_Studio/Tango.BL/DTO/SiteDTO.cs create mode 100644 Software/Visual_Studio/Tango.BL/DTO/SiteDTOBase.cs create mode 100644 Software/Visual_Studio/Tango.BL/DTO/SitesRmlDTO.cs create mode 100644 Software/Visual_Studio/Tango.BL/DTO/SitesRmlDTOBase.cs delete mode 100644 Software/Visual_Studio/Tango.BL/Entities/MachinesRml.cs delete mode 100644 Software/Visual_Studio/Tango.BL/Entities/MachinesRmlBase.cs delete mode 100644 Software/Visual_Studio/Tango.BL/Entities/OrganizationsRml.cs delete mode 100644 Software/Visual_Studio/Tango.BL/Entities/OrganizationsRmlBase.cs create mode 100644 Software/Visual_Studio/Tango.BL/Entities/Site.cs create mode 100644 Software/Visual_Studio/Tango.BL/Entities/SiteBase.cs create mode 100644 Software/Visual_Studio/Tango.BL/Entities/SitesRml.cs create mode 100644 Software/Visual_Studio/Tango.BL/Entities/SitesRmlBase.cs delete mode 100644 Software/Visual_Studio/Tango.DAL.Remote/DB/MACHINES_RMLS.cs delete mode 100644 Software/Visual_Studio/Tango.DAL.Remote/DB/ORGANIZATIONS_RMLS.cs create mode 100644 Software/Visual_Studio/Tango.DAL.Remote/DB/SITE.cs create mode 100644 Software/Visual_Studio/Tango.DAL.Remote/DB/SITES_RMLS.cs (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/DB/TCC/TCC.mdf b/Software/DB/TCC/TCC.mdf index 40ef6dfb9..7acd2ca82 100644 Binary files a/Software/DB/TCC/TCC.mdf and b/Software/DB/TCC/TCC.mdf differ diff --git a/Software/DB/TCC/TCC_log.ldf b/Software/DB/TCC/TCC_log.ldf index 46a72f239..d61145d85 100644 Binary files a/Software/DB/TCC/TCC_log.ldf and b/Software/DB/TCC/TCC_log.ldf differ diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index 45fa2dfde..ddfd3abd8 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 4b53e57cd..58b7b4e60 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Images/site.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Images/site.png new file mode 100644 index 000000000..2fee5fafa Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Images/site.png differ diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/AssemblyInfo.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..a6eebb5a8 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/AssemblyInfo.cs @@ -0,0 +1,19 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +[assembly: AssemblyTitle("Tango - Machine Studio Sites Module")] +[assembly: AssemblyVersion("1.0.0.1737")] + +[assembly: ComVisible(false)] + +[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) +)] diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Resources.Designer.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Resources.Designer.cs new file mode 100644 index 000000000..ecefa25e7 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Resources.Designer.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// +// 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.MachineStudio.Sites.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.MachineStudio.Sites.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/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Resources.resx b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/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/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Settings.Designer.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Settings.Designer.cs new file mode 100644 index 000000000..5fa894ceb --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/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.MachineStudio.Sites.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/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Settings.settings b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Settings.settings new file mode 100644 index 000000000..033d7a5e9 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/SitesModule.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/SitesModule.cs new file mode 100644 index 000000000..96d3aed49 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/SitesModule.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; +using Tango.BL.Enumerations; +using Tango.MachineStudio.Common; +using Tango.MachineStudio.Sites.Views; +using Tango.SharedUI.Helpers; + +namespace Tango.MachineStudio.Sites +{ + [StudioModule(20)] + public class SitesModule : StudioModuleBase + { + public override string Name + { + get + { + return "Sites"; + } + } + + public override string Description + { + get + { + return "Manage organizations sites and their common machine properties."; + } + } + + public override BitmapSource Image + { + get + { + return ResourceHelper.GetImageFromResources("Images/site.png"); + } + } + + public override Type MainViewType + { + get + { + return typeof(MainView); + } + } + + public override Permissions Permission + { + get + { + return Permissions.RunRMLModule; + } + } + + public override void Dispose() + { + + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Tango.MachineStudio.Sites.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Tango.MachineStudio.Sites.csproj new file mode 100644 index 000000000..95f71baa8 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Tango.MachineStudio.Sites.csproj @@ -0,0 +1,147 @@ + + + + + Debug + AnyCPU + {18A27902-9881-4556-8163-F6DF2236A14D} + library + Tango.MachineStudio.Sites + Tango.MachineStudio.Sites + v4.6.1 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + + + true + full + false + ..\..\..\Build\Machine Studio\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\..\Build\Machine Studio\Release\ + TRACE + prompt + 4 + + + + ..\..\..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.dll + + + ..\..\..\packages\MahApps.Metro.1.5.0\lib\net45\MahApps.Metro.dll + + + ..\..\..\packages\MaterialDesignColors.1.1.2\lib\net45\MaterialDesignColors.dll + + + ..\..\..\packages\MaterialDesignThemes.2.3.1.953\lib\net45\MaterialDesignThemes.Wpf.dll + + + ..\..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + + + + + ..\..\..\packages\MahApps.Metro.1.5.0\lib\net45\System.Windows.Interactivity.dll + + + + + + + + + 4.0 + + + + + + + + + + MainView.xaml + + + GlobalVersionInfo.cs + + + + Designer + MSBuild:Compile + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + {f441feee-322a-4943-b566-110e12fd3b72} + Tango.BL + + + {a34ee0f0-649d-41c8-8489-b6f1cc6924ee} + Tango.Core + + + {4206ac58-3b57-4699-8835-90bf6db01a61} + Tango.Integration + + + {bc932dbd-7cdb-488c-99e4-f02cf441f55e} + Tango.Logging + + + {d8f1ad85-526a-4f50-b6dc-d437af63d8d8} + Tango.Settings + + + {8491D07B-C1F6-4B62-A412-41B9FD2D6538} + Tango.SharedUI + + + {74e700b0-1156-4126-be40-ee450d3c3026} + Tango.Transport + + + {cb0b0aa2-bb24-4bca-a720-45e397684e12} + Tango.MachineStudio.Common + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/ViewModelLocator.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/ViewModelLocator.cs new file mode 100644 index 000000000..c06ae05e7 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/ViewModelLocator.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.DI; +using Tango.MachineStudio.Sites.ViewModels; + +namespace Tango.MachineStudio.Sites +{ + public static class ViewModelLocator + { + /// + /// Initializes a new instance of the ViewModelLocator class. + /// + static ViewModelLocator() + { + TangoIOC.Default.Register(); + } + + public static MainViewVM MainViewVM + { + get + { + return TangoIOC.Default.GetInstance(); + } + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/ViewModels/MainViewVM.cs new file mode 100644 index 000000000..d0be162dd --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/ViewModels/MainViewVM.cs @@ -0,0 +1,18 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.MachineStudio.Common; + +namespace Tango.MachineStudio.Sites.ViewModels +{ + public class MainViewVM : StudioViewModel + { + public override void OnApplicationReady() + { + + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Views/MainView.xaml new file mode 100644 index 000000000..80f9ae151 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Views/MainView.xaml @@ -0,0 +1,15 @@ + + + Comming soon... + + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Views/MainView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Views/MainView.xaml.cs new file mode 100644 index 000000000..75ced5ae2 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/Views/MainView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.MachineStudio.Sites.Views +{ + /// + /// Interaction logic for MainView.xaml + /// + public partial class MainView : UserControl + { + public MainView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/app.config b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/app.config new file mode 100644 index 000000000..97a204217 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/app.config @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/packages.config b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/packages.config new file mode 100644 index 000000000..fd88f4804 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Sites/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index 470cfe4c7..635d372c2 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -504,6 +504,10 @@ {d0186ac0-0fcf-4d3b-9619-54812b6e524b} Tango.MachineStudio.RML + + {18a27902-9881-4556-8163-f6df2236a14d} + Tango.MachineStudio.Sites + {8a65ad6a-a9b4-48c0-9301-4b7434b712f8} Tango.MachineStudio.Statistics @@ -666,7 +670,7 @@ if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)Roslyn\" - + \ No newline at end of file diff --git a/Software/Visual_Studio/Project Templates/Machine Studio Module.zip b/Software/Visual_Studio/Project Templates/Machine Studio Module.zip new file mode 100644 index 000000000..b7fb36b94 Binary files /dev/null and b/Software/Visual_Studio/Project Templates/Machine Studio Module.zip differ diff --git a/Software/Visual_Studio/Tango.BL/DTO/MachineDTOBase.cs b/Software/Visual_Studio/Tango.BL/DTO/MachineDTOBase.cs index e3adf4e0f..fa82ce992 100644 --- a/Software/Visual_Studio/Tango.BL/DTO/MachineDTOBase.cs +++ b/Software/Visual_Studio/Tango.BL/DTO/MachineDTOBase.cs @@ -53,6 +53,14 @@ namespace Tango.BL.DTO get; set; } + /// + /// site guid + /// + public String SiteGuid + { + get; set; + } + /// /// machine version guid /// diff --git a/Software/Visual_Studio/Tango.BL/DTO/MachinesRmlDTO.cs b/Software/Visual_Studio/Tango.BL/DTO/MachinesRmlDTO.cs deleted file mode 100644 index 308438b14..000000000 --- a/Software/Visual_Studio/Tango.BL/DTO/MachinesRmlDTO.cs +++ /dev/null @@ -1,14 +0,0 @@ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Tango.BL.DTO -{ - public class MachinesRmlDTO : MachinesRmlDTOBase - { - - } -} diff --git a/Software/Visual_Studio/Tango.BL/DTO/MachinesRmlDTOBase.cs b/Software/Visual_Studio/Tango.BL/DTO/MachinesRmlDTOBase.cs deleted file mode 100644 index 5ae7d3992..000000000 --- a/Software/Visual_Studio/Tango.BL/DTO/MachinesRmlDTOBase.cs +++ /dev/null @@ -1,41 +0,0 @@ - -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Tango Observables Generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. Do not modify! -// -//------------------------------------------------------------------------------ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.BL.Entities; - -namespace Tango.BL.DTO -{ - public abstract class MachinesRmlDTOBase : ObservableEntityDTO - { - - /// - /// machine guid - /// - public String MachineGuid - { - get; set; - } - - /// - /// rml guid - /// - public String RmlGuid - { - get; set; - } - - } -} diff --git a/Software/Visual_Studio/Tango.BL/DTO/OrganizationsRmlDTO.cs b/Software/Visual_Studio/Tango.BL/DTO/OrganizationsRmlDTO.cs deleted file mode 100644 index 796c1812d..000000000 --- a/Software/Visual_Studio/Tango.BL/DTO/OrganizationsRmlDTO.cs +++ /dev/null @@ -1,14 +0,0 @@ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Tango.BL.DTO -{ - public class OrganizationsRmlDTO : OrganizationsRmlDTOBase - { - - } -} diff --git a/Software/Visual_Studio/Tango.BL/DTO/OrganizationsRmlDTOBase.cs b/Software/Visual_Studio/Tango.BL/DTO/OrganizationsRmlDTOBase.cs deleted file mode 100644 index 339e846af..000000000 --- a/Software/Visual_Studio/Tango.BL/DTO/OrganizationsRmlDTOBase.cs +++ /dev/null @@ -1,41 +0,0 @@ - -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Tango Observables Generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. Do not modify! -// -//------------------------------------------------------------------------------ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.BL.Entities; - -namespace Tango.BL.DTO -{ - public abstract class OrganizationsRmlDTOBase : ObservableEntityDTO - { - - /// - /// organization guid - /// - public String OrganizationGuid - { - get; set; - } - - /// - /// rml guid - /// - public String RmlGuid - { - get; set; - } - - } -} diff --git a/Software/Visual_Studio/Tango.BL/DTO/SiteDTO.cs b/Software/Visual_Studio/Tango.BL/DTO/SiteDTO.cs new file mode 100644 index 000000000..320de2763 --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/DTO/SiteDTO.cs @@ -0,0 +1,14 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.BL.DTO +{ + public class SiteDTO : SiteDTOBase + { + + } +} diff --git a/Software/Visual_Studio/Tango.BL/DTO/SiteDTOBase.cs b/Software/Visual_Studio/Tango.BL/DTO/SiteDTOBase.cs new file mode 100644 index 000000000..47d7acc95 --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/DTO/SiteDTOBase.cs @@ -0,0 +1,49 @@ + +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Tango Observables Generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. Do not modify! +// +//------------------------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; + +namespace Tango.BL.DTO +{ + public abstract class SiteDTOBase : ObservableEntityDTO + { + + /// + /// organization guid + /// + public String OrganizationGuid + { + get; set; + } + + /// + /// name + /// + public String Name + { + get; set; + } + + /// + /// description + /// + public String Description + { + get; set; + } + + } +} diff --git a/Software/Visual_Studio/Tango.BL/DTO/SitesRmlDTO.cs b/Software/Visual_Studio/Tango.BL/DTO/SitesRmlDTO.cs new file mode 100644 index 000000000..527d710d0 --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/DTO/SitesRmlDTO.cs @@ -0,0 +1,14 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.BL.DTO +{ + public class SitesRmlDTO : SitesRmlDTOBase + { + + } +} diff --git a/Software/Visual_Studio/Tango.BL/DTO/SitesRmlDTOBase.cs b/Software/Visual_Studio/Tango.BL/DTO/SitesRmlDTOBase.cs new file mode 100644 index 000000000..1373fedd6 --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/DTO/SitesRmlDTOBase.cs @@ -0,0 +1,41 @@ + +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Tango Observables Generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. Do not modify! +// +//------------------------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; + +namespace Tango.BL.DTO +{ + public abstract class SitesRmlDTOBase : ObservableEntityDTO + { + + /// + /// site guid + /// + public String SiteGuid + { + get; set; + } + + /// + /// rml guid + /// + public String RmlGuid + { + get; set; + } + + } +} diff --git a/Software/Visual_Studio/Tango.BL/Entities/HardwareBlowerBase.cs b/Software/Visual_Studio/Tango.BL/Entities/HardwareBlowerBase.cs index de376da41..bbc55d245 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/HardwareBlowerBase.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/HardwareBlowerBase.cs @@ -131,6 +131,8 @@ namespace Tango.BL.Entities [Column("VOLTAGE")] [Description("Voltage Description")] + [Range(-10000,1000000)] + public Double Voltage { get diff --git a/Software/Visual_Studio/Tango.BL/Entities/MachineBase.cs b/Software/Visual_Studio/Tango.BL/Entities/MachineBase.cs index 4f989aeb2..c02b103dd 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/MachineBase.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/MachineBase.cs @@ -197,6 +197,31 @@ namespace Tango.BL.Entities } } + protected String _siteguid; + + /// + /// Gets or sets the machinebase site guid. + /// + + [Column("SITE_GUID")] + + public String SiteGuid + { + get + { + return _siteguid; + } + + set + { + if (_siteguid != value) + { + _siteguid = value; + + } + } + } + protected String _machineversionguid; /// diff --git a/Software/Visual_Studio/Tango.BL/Entities/MachinesRml.cs b/Software/Visual_Studio/Tango.BL/Entities/MachinesRml.cs deleted file mode 100644 index 6fe2ef16e..000000000 --- a/Software/Visual_Studio/Tango.BL/Entities/MachinesRml.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Tango.BL.Entities -{ - public class MachinesRml : MachinesRmlBase - { - } -} diff --git a/Software/Visual_Studio/Tango.BL/Entities/MachinesRmlBase.cs b/Software/Visual_Studio/Tango.BL/Entities/MachinesRmlBase.cs deleted file mode 100644 index efb9cd997..000000000 --- a/Software/Visual_Studio/Tango.BL/Entities/MachinesRmlBase.cs +++ /dev/null @@ -1,86 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Tango Observables Generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. Do not modify! -// -//------------------------------------------------------------------------------ - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using System.Xml.Serialization; -using Newtonsoft.Json; -using System.Linq; -using Tango.DAL.Remote.DB; -using Tango.Core; -using System.ComponentModel; - -namespace Tango.BL.Entities -{ - [Table("MACHINES_RMLS")] - public abstract class MachinesRmlBase : ObservableEntity - { - - protected String _machineguid; - - /// - /// Gets or sets the machinesrmlbase machine guid. - /// - - [Column("MACHINE_GUID")] - - public String MachineGuid - { - get - { - return _machineguid; - } - - set - { - if (_machineguid != value) - { - _machineguid = value; - - } - } - } - - protected String _rmlguid; - - /// - /// Gets or sets the machinesrmlbase rml guid. - /// - - [Column("RML_GUID")] - - public String RmlGuid - { - get - { - return _rmlguid; - } - - set - { - if (_rmlguid != value) - { - _rmlguid = value; - - } - } - } - - /// - /// Initializes a new instance of the class. - /// - public MachinesRmlBase() : base() - { - } - } -} diff --git a/Software/Visual_Studio/Tango.BL/Entities/OrganizationsRml.cs b/Software/Visual_Studio/Tango.BL/Entities/OrganizationsRml.cs deleted file mode 100644 index 70c8fb66f..000000000 --- a/Software/Visual_Studio/Tango.BL/Entities/OrganizationsRml.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Tango.BL.Entities -{ - public class OrganizationsRml : OrganizationsRmlBase - { - } -} diff --git a/Software/Visual_Studio/Tango.BL/Entities/OrganizationsRmlBase.cs b/Software/Visual_Studio/Tango.BL/Entities/OrganizationsRmlBase.cs deleted file mode 100644 index d1f338428..000000000 --- a/Software/Visual_Studio/Tango.BL/Entities/OrganizationsRmlBase.cs +++ /dev/null @@ -1,86 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Tango Observables Generator -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. Do not modify! -// -//------------------------------------------------------------------------------ - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -using System.Xml.Serialization; -using Newtonsoft.Json; -using System.Linq; -using Tango.DAL.Remote.DB; -using Tango.Core; -using System.ComponentModel; - -namespace Tango.BL.Entities -{ - [Table("ORGANIZATIONS_RMLS")] - public abstract class OrganizationsRmlBase : ObservableEntity - { - - protected String _organizationguid; - - /// - /// Gets or sets the organizationsrmlbase organization guid. - /// - - [Column("ORGANIZATION_GUID")] - - public String OrganizationGuid - { - get - { - return _organizationguid; - } - - set - { - if (_organizationguid != value) - { - _organizationguid = value; - - } - } - } - - protected String _rmlguid; - - /// - /// Gets or sets the organizationsrmlbase rml guid. - /// - - [Column("RML_GUID")] - - public String RmlGuid - { - get - { - return _rmlguid; - } - - set - { - if (_rmlguid != value) - { - _rmlguid = value; - - } - } - } - - /// - /// Initializes a new instance of the class. - /// - public OrganizationsRmlBase() : base() - { - } - } -} diff --git a/Software/Visual_Studio/Tango.BL/Entities/Site.cs b/Software/Visual_Studio/Tango.BL/Entities/Site.cs new file mode 100644 index 000000000..d88a00567 --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/Entities/Site.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.BL.Entities +{ + public class Site : SiteBase + { + } +} diff --git a/Software/Visual_Studio/Tango.BL/Entities/SiteBase.cs b/Software/Visual_Studio/Tango.BL/Entities/SiteBase.cs new file mode 100644 index 000000000..4294b2daf --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/Entities/SiteBase.cs @@ -0,0 +1,137 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Tango Observables Generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. Do not modify! +// +//------------------------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Xml.Serialization; +using Newtonsoft.Json; +using System.Linq; +using Tango.DAL.Remote.DB; +using Tango.Core; +using System.ComponentModel; + +namespace Tango.BL.Entities +{ + [Table("SITES")] + public abstract class SiteBase : ObservableEntity + { + + public event EventHandler NameChanged; + + public event EventHandler DescriptionChanged; + + protected String _organizationguid; + + /// + /// Gets or sets the sitebase organization guid. + /// + + [Column("ORGANIZATION_GUID")] + + public String OrganizationGuid + { + get + { + return _organizationguid; + } + + set + { + if (_organizationguid != value) + { + _organizationguid = value; + + } + } + } + + protected String _name; + + /// + /// Gets or sets the sitebase name. + /// + + [Column("NAME")] + + public String Name + { + get + { + return _name; + } + + set + { + if (_name != value) + { + _name = value; + + OnNameChanged(value); + + } + } + } + + protected String _description; + + /// + /// Gets or sets the sitebase description. + /// + + [Column("DESCRIPTION")] + + public String Description + { + get + { + return _description; + } + + set + { + if (_description != value) + { + _description = value; + + OnDescriptionChanged(value); + + } + } + } + + /// + /// Called when the Name has changed. + /// + protected virtual void OnNameChanged(String name) + { + NameChanged?.Invoke(this, name); + RaisePropertyChanged(nameof(Name)); + } + + /// + /// Called when the Description has changed. + /// + protected virtual void OnDescriptionChanged(String description) + { + DescriptionChanged?.Invoke(this, description); + RaisePropertyChanged(nameof(Description)); + } + + /// + /// Initializes a new instance of the class. + /// + public SiteBase() : base() + { + } + } +} diff --git a/Software/Visual_Studio/Tango.BL/Entities/SitesRml.cs b/Software/Visual_Studio/Tango.BL/Entities/SitesRml.cs new file mode 100644 index 000000000..1d6dafe8b --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/Entities/SitesRml.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.BL.Entities +{ + public class SitesRml : SitesRmlBase + { + } +} diff --git a/Software/Visual_Studio/Tango.BL/Entities/SitesRmlBase.cs b/Software/Visual_Studio/Tango.BL/Entities/SitesRmlBase.cs new file mode 100644 index 000000000..0538069b4 --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/Entities/SitesRmlBase.cs @@ -0,0 +1,86 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Tango Observables Generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. Do not modify! +// +//------------------------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Xml.Serialization; +using Newtonsoft.Json; +using System.Linq; +using Tango.DAL.Remote.DB; +using Tango.Core; +using System.ComponentModel; + +namespace Tango.BL.Entities +{ + [Table("SITES_RMLS")] + public abstract class SitesRmlBase : ObservableEntity + { + + protected String _siteguid; + + /// + /// Gets or sets the sitesrmlbase site guid. + /// + + [Column("SITE_GUID")] + + public String SiteGuid + { + get + { + return _siteguid; + } + + set + { + if (_siteguid != value) + { + _siteguid = value; + + } + } + } + + protected String _rmlguid; + + /// + /// Gets or sets the sitesrmlbase rml guid. + /// + + [Column("RML_GUID")] + + public String RmlGuid + { + get + { + return _rmlguid; + } + + set + { + if (_rmlguid != value) + { + _rmlguid = value; + + } + } + } + + /// + /// Initializes a new instance of the class. + /// + public SitesRmlBase() : base() + { + } + } +} diff --git a/Software/Visual_Studio/Tango.BL/ObservablesContext.cs b/Software/Visual_Studio/Tango.BL/ObservablesContext.cs index 25c3b5682..d47f6514b 100644 --- a/Software/Visual_Studio/Tango.BL/ObservablesContext.cs +++ b/Software/Visual_Studio/Tango.BL/ObservablesContext.cs @@ -414,14 +414,6 @@ namespace Tango.BL get; set; } - /// - /// Gets or sets the MachinesRmls. - /// - public DbSet MachinesRmls - { - get; set; - } - /// /// Gets or sets the MediaConditions. /// @@ -462,14 +454,6 @@ namespace Tango.BL get; set; } - /// - /// Gets or sets the OrganizationsRmls. - /// - public DbSet OrganizationsRmls - { - get; set; - } - /// /// Gets or sets the Permissions. /// @@ -526,6 +510,22 @@ namespace Tango.BL get; set; } + /// + /// Gets or sets the Sites. + /// + public DbSet Sites + { + get; set; + } + + /// + /// Gets or sets the SitesRmls. + /// + public DbSet SitesRmls + { + get; set; + } + /// /// Gets or sets the SpoolTypes. /// diff --git a/Software/Visual_Studio/Tango.BL/ObservablesEntitiesAdapterExtension.cs b/Software/Visual_Studio/Tango.BL/ObservablesEntitiesAdapterExtension.cs index cb259995b..139c90158 100644 --- a/Software/Visual_Studio/Tango.BL/ObservablesEntitiesAdapterExtension.cs +++ b/Software/Visual_Studio/Tango.BL/ObservablesEntitiesAdapterExtension.cs @@ -1781,42 +1781,6 @@ namespace Tango.BL } - private ObservableCollection _machinesrmls; - /// - /// Gets or sets the MachinesRmls. - /// - public ObservableCollection MachinesRmls - { - get - { - return _machinesrmls; - } - - set - { - _machinesrmls = value; RaisePropertyChanged(nameof(MachinesRmls)); - } - - } - - private ICollectionView _machinesrmlsViewSource; - /// - /// Gets or sets the MachinesRmls View Source. - /// - public ICollectionView MachinesRmlsViewSource - { - get - { - return _machinesrmlsViewSource; - } - - set - { - _machinesrmlsViewSource = value; RaisePropertyChanged(nameof(MachinesRmlsViewSource)); - } - - } - private ObservableCollection _mediaconditions; /// /// Gets or sets the MediaConditions. @@ -1997,42 +1961,6 @@ namespace Tango.BL } - private ObservableCollection _organizationsrmls; - /// - /// Gets or sets the OrganizationsRmls. - /// - public ObservableCollection OrganizationsRmls - { - get - { - return _organizationsrmls; - } - - set - { - _organizationsrmls = value; RaisePropertyChanged(nameof(OrganizationsRmls)); - } - - } - - private ICollectionView _organizationsrmlsViewSource; - /// - /// Gets or sets the OrganizationsRmls View Source. - /// - public ICollectionView OrganizationsRmlsViewSource - { - get - { - return _organizationsrmlsViewSource; - } - - set - { - _organizationsrmlsViewSource = value; RaisePropertyChanged(nameof(OrganizationsRmlsViewSource)); - } - - } - private ObservableCollection _permissions; /// /// Gets or sets the Permissions. @@ -2285,6 +2213,78 @@ namespace Tango.BL } + private ObservableCollection _sites; + /// + /// Gets or sets the Sites. + /// + public ObservableCollection Sites + { + get + { + return _sites; + } + + set + { + _sites = value; RaisePropertyChanged(nameof(Sites)); + } + + } + + private ICollectionView _sitesViewSource; + /// + /// Gets or sets the Sites View Source. + /// + public ICollectionView SitesViewSource + { + get + { + return _sitesViewSource; + } + + set + { + _sitesViewSource = value; RaisePropertyChanged(nameof(SitesViewSource)); + } + + } + + private ObservableCollection _sitesrmls; + /// + /// Gets or sets the SitesRmls. + /// + public ObservableCollection SitesRmls + { + get + { + return _sitesrmls; + } + + set + { + _sitesrmls = value; RaisePropertyChanged(nameof(SitesRmls)); + } + + } + + private ICollectionView _sitesrmlsViewSource; + /// + /// Gets or sets the SitesRmls View Source. + /// + public ICollectionView SitesRmlsViewSource + { + get + { + return _sitesrmlsViewSource; + } + + set + { + _sitesrmlsViewSource = value; RaisePropertyChanged(nameof(SitesRmlsViewSource)); + } + + } + private ObservableCollection _spooltypes; /// /// Gets or sets the SpoolTypes. @@ -2893,8 +2893,6 @@ namespace Tango.BL MachinesEventsViewSource = CreateCollectionView(MachinesEvents); - MachinesRmlsViewSource = CreateCollectionView(MachinesRmls); - MediaConditionsViewSource = CreateCollectionView(MediaConditions); MediaMaterialsViewSource = CreateCollectionView(MediaMaterials); @@ -2905,8 +2903,6 @@ namespace Tango.BL OrganizationsViewSource = CreateCollectionView(Organizations); - OrganizationsRmlsViewSource = CreateCollectionView(OrganizationsRmls); - PermissionsViewSource = CreateCollectionView(Permissions); ProcessParametersTablesViewSource = CreateCollectionView(ProcessParametersTables); @@ -2921,6 +2917,10 @@ namespace Tango.BL SegmentsViewSource = CreateCollectionView(Segments); + SitesViewSource = CreateCollectionView(Sites); + + SitesRmlsViewSource = CreateCollectionView(SitesRmls); + SpoolTypesViewSource = CreateCollectionView(SpoolTypes); SpoolsViewSource = CreateCollectionView(Spools); diff --git a/Software/Visual_Studio/Tango.BL/ObservablesStaticCollectionsExtension.cs b/Software/Visual_Studio/Tango.BL/ObservablesStaticCollectionsExtension.cs index 3b24aa506..e509d0e3c 100644 --- a/Software/Visual_Studio/Tango.BL/ObservablesStaticCollectionsExtension.cs +++ b/Software/Visual_Studio/Tango.BL/ObservablesStaticCollectionsExtension.cs @@ -1781,42 +1781,6 @@ namespace Tango.BL } - private ObservableCollection _machinesrmls; - /// - /// Gets or sets the MachinesRmls. - /// - public ObservableCollection MachinesRmls - { - get - { - return _machinesrmls; - } - - set - { - _machinesrmls = value; RaisePropertyChanged(nameof(MachinesRmls)); - } - - } - - private ICollectionView _machinesrmlsViewSource; - /// - /// Gets or sets the MachinesRmls View Source. - /// - public ICollectionView MachinesRmlsViewSource - { - get - { - return _machinesrmlsViewSource; - } - - set - { - _machinesrmlsViewSource = value; RaisePropertyChanged(nameof(MachinesRmlsViewSource)); - } - - } - private ObservableCollection _mediaconditions; /// /// Gets or sets the MediaConditions. @@ -1997,42 +1961,6 @@ namespace Tango.BL } - private ObservableCollection _organizationsrmls; - /// - /// Gets or sets the OrganizationsRmls. - /// - public ObservableCollection OrganizationsRmls - { - get - { - return _organizationsrmls; - } - - set - { - _organizationsrmls = value; RaisePropertyChanged(nameof(OrganizationsRmls)); - } - - } - - private ICollectionView _organizationsrmlsViewSource; - /// - /// Gets or sets the OrganizationsRmls View Source. - /// - public ICollectionView OrganizationsRmlsViewSource - { - get - { - return _organizationsrmlsViewSource; - } - - set - { - _organizationsrmlsViewSource = value; RaisePropertyChanged(nameof(OrganizationsRmlsViewSource)); - } - - } - private ObservableCollection _permissions; /// /// Gets or sets the Permissions. @@ -2285,6 +2213,78 @@ namespace Tango.BL } + private ObservableCollection _sites; + /// + /// Gets or sets the Sites. + /// + public ObservableCollection Sites + { + get + { + return _sites; + } + + set + { + _sites = value; RaisePropertyChanged(nameof(Sites)); + } + + } + + private ICollectionView _sitesViewSource; + /// + /// Gets or sets the Sites View Source. + /// + public ICollectionView SitesViewSource + { + get + { + return _sitesViewSource; + } + + set + { + _sitesViewSource = value; RaisePropertyChanged(nameof(SitesViewSource)); + } + + } + + private ObservableCollection _sitesrmls; + /// + /// Gets or sets the SitesRmls. + /// + public ObservableCollection SitesRmls + { + get + { + return _sitesrmls; + } + + set + { + _sitesrmls = value; RaisePropertyChanged(nameof(SitesRmls)); + } + + } + + private ICollectionView _sitesrmlsViewSource; + /// + /// Gets or sets the SitesRmls View Source. + /// + public ICollectionView SitesRmlsViewSource + { + get + { + return _sitesrmlsViewSource; + } + + set + { + _sitesrmlsViewSource = value; RaisePropertyChanged(nameof(SitesRmlsViewSource)); + } + + } + private ObservableCollection _spooltypes; /// /// Gets or sets the SpoolTypes. @@ -2893,8 +2893,6 @@ namespace Tango.BL MachinesEventsViewSource = CreateCollectionView(MachinesEvents); - MachinesRmlsViewSource = CreateCollectionView(MachinesRmls); - MediaConditionsViewSource = CreateCollectionView(MediaConditions); MediaMaterialsViewSource = CreateCollectionView(MediaMaterials); @@ -2905,8 +2903,6 @@ namespace Tango.BL OrganizationsViewSource = CreateCollectionView(Organizations); - OrganizationsRmlsViewSource = CreateCollectionView(OrganizationsRmls); - PermissionsViewSource = CreateCollectionView(Permissions); ProcessParametersTablesViewSource = CreateCollectionView(ProcessParametersTables); @@ -2921,6 +2917,10 @@ namespace Tango.BL SegmentsViewSource = CreateCollectionView(Segments); + SitesViewSource = CreateCollectionView(Sites); + + SitesRmlsViewSource = CreateCollectionView(SitesRmls); + SpoolTypesViewSource = CreateCollectionView(SpoolTypes); SpoolsViewSource = CreateCollectionView(Spools); diff --git a/Software/Visual_Studio/Tango.BL/Tango.BL.csproj b/Software/Visual_Studio/Tango.BL/Tango.BL.csproj index c3c1b9ab9..d75cdc0c1 100644 --- a/Software/Visual_Studio/Tango.BL/Tango.BL.csproj +++ b/Software/Visual_Studio/Tango.BL/Tango.BL.csproj @@ -206,8 +206,6 @@ - - @@ -222,8 +220,6 @@ - - @@ -238,6 +234,10 @@ + + + + @@ -323,8 +323,6 @@ - - @@ -332,8 +330,6 @@ - - @@ -341,6 +337,10 @@ + + + + diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/MACHINE.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/MACHINE.cs index 9e83e7e4d..0508fc99e 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/MACHINE.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/MACHINE.cs @@ -30,6 +30,7 @@ namespace Tango.DAL.Remote.DB public string NAME { get; set; } public System.DateTime PRODUCTION_DATE { get; set; } public string ORGANIZATION_GUID { get; set; } + public string SITE_GUID { get; set; } public string MACHINE_VERSION_GUID { get; set; } public string CONFIGURATION_GUID { get; set; } public string DEFAULT_RML_GUID { get; set; } diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/MACHINES_RMLS.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/MACHINES_RMLS.cs deleted file mode 100644 index 64cdfe830..000000000 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/MACHINES_RMLS.cs +++ /dev/null @@ -1,23 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated from a template. -// -// Manual changes to this file may cause unexpected behavior in your application. -// Manual changes to this file will be overwritten if the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Tango.DAL.Remote.DB -{ - using System; - using System.Collections.Generic; - - public partial class MACHINES_RMLS - { - public int ID { get; set; } - public string GUID { get; set; } - public System.DateTime LAST_UPDATED { get; set; } - public string MACHINE_GUID { get; set; } - public string RML_GUID { get; set; } - } -} diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/ORGANIZATIONS_RMLS.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/ORGANIZATIONS_RMLS.cs deleted file mode 100644 index 1db95419e..000000000 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/ORGANIZATIONS_RMLS.cs +++ /dev/null @@ -1,23 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated from a template. -// -// Manual changes to this file may cause unexpected behavior in your application. -// Manual changes to this file will be overwritten if the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Tango.DAL.Remote.DB -{ - using System; - using System.Collections.Generic; - - public partial class ORGANIZATIONS_RMLS - { - public int ID { get; set; } - public string GUID { get; set; } - public System.DateTime LAST_UPDATED { get; set; } - public string ORGANIZATION_GUID { get; set; } - public string RML_GUID { get; set; } - } -} diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Context.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Context.cs index fc248bbfe..9f81121ca 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Context.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Context.cs @@ -74,13 +74,11 @@ namespace Tango.DAL.Remote.DB public virtual DbSet MACHINE_VERSIONS { get; set; } public virtual DbSet MACHINES { get; set; } public virtual DbSet MACHINES_EVENTS { get; set; } - public virtual DbSet MACHINES_RMLS { get; set; } public virtual DbSet MEDIA_CONDITIONS { get; set; } public virtual DbSet MEDIA_MATERIALS { get; set; } public virtual DbSet MEDIA_PURPOSES { get; set; } public virtual DbSet MID_TANK_TYPES { get; set; } public virtual DbSet ORGANIZATIONS { get; set; } - public virtual DbSet ORGANIZATIONS_RMLS { get; set; } public virtual DbSet PERMISSIONS { get; set; } public virtual DbSet PROCESS_PARAMETERS_TABLES { get; set; } public virtual DbSet PROCESS_PARAMETERS_TABLES_GROUPS { get; set; } @@ -88,6 +86,8 @@ namespace Tango.DAL.Remote.DB public virtual DbSet ROLES { get; set; } public virtual DbSet ROLES_PERMISSIONS { get; set; } public virtual DbSet SEGMENTS { get; set; } + public virtual DbSet SITES { get; set; } + public virtual DbSet SITES_RMLS { get; set; } public virtual DbSet SPOOL_TYPES { get; set; } public virtual DbSet SPOOLS { get; set; } public virtual DbSet sysdiagrams { get; set; } diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx index 44dffd473..2c003669e 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx @@ -708,6 +708,7 @@ + @@ -749,16 +750,6 @@ - - - - - - - - - - @@ -811,16 +802,6 @@ - - - - - - - - - - @@ -941,6 +922,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -2237,13 +2239,11 @@ - - @@ -2251,6 +2251,8 @@ + + @@ -2645,13 +2647,11 @@ - - @@ -2659,6 +2659,8 @@ + + @@ -3808,6 +3810,7 @@ + @@ -3862,16 +3865,6 @@ - - - - - - - - - - @@ -3933,16 +3926,6 @@ - - - - - - - - - - @@ -4086,6 +4069,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -6124,6 +6128,7 @@ + @@ -6150,17 +6155,6 @@ - - - - - - - - - - - @@ -6218,17 +6212,6 @@ - - - - - - - - - - - @@ -6356,6 +6339,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram index a30733407..e7b00e86f 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram @@ -5,82 +5,82 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/SITE.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/SITE.cs new file mode 100644 index 000000000..10dcaef11 --- /dev/null +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/SITE.cs @@ -0,0 +1,24 @@ +//------------------------------------------------------------------------------ +// +// This code was generated from a template. +// +// Manual changes to this file may cause unexpected behavior in your application. +// Manual changes to this file will be overwritten if the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Tango.DAL.Remote.DB +{ + using System; + using System.Collections.Generic; + + public partial class SITE + { + public int ID { get; set; } + public string GUID { get; set; } + public System.DateTime LAST_UPDATED { get; set; } + public string ORGANIZATION_GUID { get; set; } + public string NAME { get; set; } + public string DESCRIPTION { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/SITES_RMLS.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/SITES_RMLS.cs new file mode 100644 index 000000000..ea22adbf8 --- /dev/null +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/SITES_RMLS.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// This code was generated from a template. +// +// Manual changes to this file may cause unexpected behavior in your application. +// Manual changes to this file will be overwritten if the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Tango.DAL.Remote.DB +{ + using System; + using System.Collections.Generic; + + public partial class SITES_RMLS + { + public int ID { get; set; } + public string GUID { get; set; } + public System.DateTime LAST_UPDATED { get; set; } + public string SITE_GUID { get; set; } + public string RML_GUID { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.DAL.Remote/Tango.DAL.Remote.csproj b/Software/Visual_Studio/Tango.DAL.Remote/Tango.DAL.Remote.csproj index cda3f47c2..4150c2771 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/Tango.DAL.Remote.csproj +++ b/Software/Visual_Studio/Tango.DAL.Remote/Tango.DAL.Remote.csproj @@ -204,9 +204,6 @@ RemoteADO.tt - - RemoteADO.tt - RemoteADO.tt @@ -228,9 +225,6 @@ RemoteADO.tt - - RemoteADO.tt - RemoteADO.tt @@ -267,6 +261,12 @@ RemoteADO.tt + + RemoteADO.tt + + + RemoteADO.tt + RemoteADO.tt diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln index 9d0bc3083..bfdbb9c8a 100644 --- a/Software/Visual_Studio/Tango.sln +++ b/Software/Visual_Studio/Tango.sln @@ -331,6 +331,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.PPC.Browser", "PPC\Mo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.PPC.Packages.CefInstaller", "PPC\Packages\Tango.PPC.Packages.CefInstaller\Tango.PPC.Packages.CefInstaller.csproj", "{DF64460A-6617-4338-872A-DC43FD994C48}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.MachineStudio.Sites", "MachineStudio\Modules\Tango.MachineStudio.Sites\Tango.MachineStudio.Sites.csproj", "{18A27902-9881-4556-8163-F6DF2236A14D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AppVeyor|Any CPU = AppVeyor|Any CPU @@ -5903,6 +5905,46 @@ Global {DF64460A-6617-4338-872A-DC43FD994C48}.Release|x64.Build.0 = Release|Any CPU {DF64460A-6617-4338-872A-DC43FD994C48}.Release|x86.ActiveCfg = Release|Any CPU {DF64460A-6617-4338-872A-DC43FD994C48}.Release|x86.Build.0 = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.AppVeyor|Any CPU.ActiveCfg = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.AppVeyor|Any CPU.Build.0 = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.AppVeyor|ARM.ActiveCfg = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.AppVeyor|ARM.Build.0 = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.AppVeyor|ARM64.ActiveCfg = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.AppVeyor|ARM64.Build.0 = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.AppVeyor|x64.ActiveCfg = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.AppVeyor|x64.Build.0 = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.AppVeyor|x86.ActiveCfg = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.AppVeyor|x86.Build.0 = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Debug|ARM.ActiveCfg = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Debug|ARM.Build.0 = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Debug|ARM64.Build.0 = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Debug|x64.ActiveCfg = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Debug|x64.Build.0 = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Debug|x86.ActiveCfg = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Debug|x86.Build.0 = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.DefaultBuild|Any CPU.ActiveCfg = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.DefaultBuild|Any CPU.Build.0 = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.DefaultBuild|ARM.ActiveCfg = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.DefaultBuild|ARM.Build.0 = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.DefaultBuild|ARM64.ActiveCfg = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.DefaultBuild|ARM64.Build.0 = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.DefaultBuild|x64.ActiveCfg = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.DefaultBuild|x64.Build.0 = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.DefaultBuild|x86.ActiveCfg = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.DefaultBuild|x86.Build.0 = Debug|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Release|Any CPU.Build.0 = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Release|ARM.ActiveCfg = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Release|ARM.Build.0 = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Release|ARM64.ActiveCfg = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Release|ARM64.Build.0 = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Release|x64.ActiveCfg = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Release|x64.Build.0 = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Release|x86.ActiveCfg = Release|Any CPU + {18A27902-9881-4556-8163-F6DF2236A14D}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -6013,6 +6055,7 @@ Global {F3746F2B-E4AE-498B-9D42-74F95D992460} = {C81ED1A3-D18C-4D80-A8F5-061994A14A60} {F02EAA84-AD59-465B-99A2-4422C13BFB72} = {0048447D-1D94-4E60-9DAD-7349C777CB4E} {DF64460A-6617-4338-872A-DC43FD994C48} = {E728CBD9-1AF4-4814-A218-E4BD26E7EDEA} + {18A27902-9881-4556-8163-F6DF2236A14D} = {B2AF4F3F-2828-47C3-8F3E-A0EA0BD66FF8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7986F7F4-A86A-4994-B1B6-0988D7F057B6} -- cgit v1.3.1