aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Software/DB/Tango.mdfbin75497472 -> 75497472 bytes
-rw-r--r--Software/DB/Tango_log.ldfbin15400960 -> 15400960 bytes
-rw-r--r--Software/Graphics/machine-update.pngbin0 -> 54914 bytes
-rw-r--r--Software/PMR/Messages/Synchronization/CheckForUpdateRequest.proto10
-rw-r--r--Software/PMR/Messages/Synchronization/CheckForUpdateResponse.proto10
-rw-r--r--Software/PMR/Messages/Synchronization/DownloadUpdateRequest.proto9
-rw-r--r--Software/PMR/Messages/Synchronization/DownloadUpdateResponse.proto18
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs4
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs53
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs287
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs16
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateSteps.cs21
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/NavigationView.cs1
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj6
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindow.xaml19
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindow.xaml.cs51
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindowVM.cs90
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Images/machine-update.pngbin0 -> 54914 bytes
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Images/right-arrow-64.pngbin0 -> 690 bytes
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs1
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Properties/AssemblyInfo.cs2
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj13
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs13
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/LayoutViewVM.cs9
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineSetupViewVM.cs7
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs170
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml9
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml129
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml.cs46
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MainView.xaml1
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/ViewsContracts/IMachineUpdateView.cs19
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Updater/MainWindow.xaml.cs50
-rw-r--r--Software/Visual_Studio/Tango.Logging/ConsoleWindow.xaml2
-rw-r--r--Software/Visual_Studio/Tango.Logging/ConsoleWindow.xaml.cs2
-rw-r--r--Software/Visual_Studio/Tango.PMR/Synchronization/CheckForUpdateRequest.cs188
-rw-r--r--Software/Visual_Studio/Tango.PMR/Synchronization/CheckForUpdateResponse.cs188
-rw-r--r--Software/Visual_Studio/Tango.PMR/Synchronization/DownloadUpdateRequest.cs160
-rw-r--r--Software/Visual_Studio/Tango.PMR/Synchronization/DownloadUpdateResponse.cs359
-rw-r--r--Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj11
-rw-r--r--Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs15
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/SynchronizationController.cs96
41 files changed, 2028 insertions, 57 deletions
diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf
index 9d864e6a7..3e25b6208 100644
--- a/Software/DB/Tango.mdf
+++ b/Software/DB/Tango.mdf
Binary files differ
diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf
index 1e080784d..a4d8c33d4 100644
--- a/Software/DB/Tango_log.ldf
+++ b/Software/DB/Tango_log.ldf
Binary files differ
diff --git a/Software/Graphics/machine-update.png b/Software/Graphics/machine-update.png
new file mode 100644
index 000000000..3e49520dd
--- /dev/null
+++ b/Software/Graphics/machine-update.png
Binary files differ
diff --git a/Software/PMR/Messages/Synchronization/CheckForUpdateRequest.proto b/Software/PMR/Messages/Synchronization/CheckForUpdateRequest.proto
new file mode 100644
index 000000000..4b1da8764
--- /dev/null
+++ b/Software/PMR/Messages/Synchronization/CheckForUpdateRequest.proto
@@ -0,0 +1,10 @@
+syntax = "proto3";
+
+package Tango.PMR.Synchronization;
+option java_package = "com.twine.tango.pmr.synchronization";
+
+message CheckForUpdateRequest
+{
+ string SerialNumber = 1;
+ string Version = 2;
+} \ No newline at end of file
diff --git a/Software/PMR/Messages/Synchronization/CheckForUpdateResponse.proto b/Software/PMR/Messages/Synchronization/CheckForUpdateResponse.proto
new file mode 100644
index 000000000..30e2b6fbb
--- /dev/null
+++ b/Software/PMR/Messages/Synchronization/CheckForUpdateResponse.proto
@@ -0,0 +1,10 @@
+syntax = "proto3";
+
+package Tango.PMR.Synchronization;
+option java_package = "com.twine.tango.pmr.synchronization";
+
+message CheckForUpdateResponse
+{
+ bool IsUpdateAvailable = 1;
+ string Version = 2;
+} \ No newline at end of file
diff --git a/Software/PMR/Messages/Synchronization/DownloadUpdateRequest.proto b/Software/PMR/Messages/Synchronization/DownloadUpdateRequest.proto
new file mode 100644
index 000000000..98b302f85
--- /dev/null
+++ b/Software/PMR/Messages/Synchronization/DownloadUpdateRequest.proto
@@ -0,0 +1,9 @@
+syntax = "proto3";
+
+package Tango.PMR.Synchronization;
+option java_package = "com.twine.tango.pmr.synchronization";
+
+message DownloadUpdateRequest
+{
+ string SerialNumber = 1;
+} \ No newline at end of file
diff --git a/Software/PMR/Messages/Synchronization/DownloadUpdateResponse.proto b/Software/PMR/Messages/Synchronization/DownloadUpdateResponse.proto
new file mode 100644
index 000000000..db70e7d92
--- /dev/null
+++ b/Software/PMR/Messages/Synchronization/DownloadUpdateResponse.proto
@@ -0,0 +1,18 @@
+syntax = "proto3";
+
+package Tango.PMR.Synchronization;
+option java_package = "com.twine.tango.pmr.synchronization";
+
+message DownloadUpdateResponse
+{
+ string Version = 1;
+
+ string FtpAddress = 2;
+ string FtpFilePath = 3;
+ string FtpUserName = 4;
+ string FtpPassword = 5;
+
+ string DbAddress = 6;
+ string DbUserName = 7;
+ string DbPassword = 8;
+} \ No newline at end of file
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 8d4d5fa0a..252491669 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs
@@ -196,8 +196,8 @@ namespace Tango.PPC.Common.MachineSetup
LogManager.Log($"Initializing {nameof(ExaminerSequenceConfigurationRunner)}...");
ExaminerSequenceConfigurationRunner runner = new ExaminerSequenceConfigurationRunner(
- Path.Combine(_newPackageTempFolder, "Synchronization Scripts", "config.xml"),
- Path.Combine(_newPackageTempFolder, "Synchronization Scripts"),
+ Path.Combine(_newPackageTempFolder, "Provision Scripts", "config.xml"),
+ Path.Combine(_newPackageTempFolder, "Provision Scripts"),
new ExaminerSequenceDataSource()
{
Address = remote_address,
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs
new file mode 100644
index 000000000..fd565b84a
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.PMR.Synchronization;
+
+namespace Tango.PPC.Common.MachineUpdate
+{
+ public interface IMachineUpdateManager
+ {
+ /// <summary>
+ /// Gets the current setup step.
+ /// </summary>
+ MachineUpdateSteps CurrentStep { get; }
+
+ /// <summary>
+ /// Occurs when there is a text log message available.
+ /// </summary>
+ event EventHandler<String> ProgressLog;
+
+ /// <summary>
+ /// Gets the downloading packages step progress.
+ /// </summary>
+ double DownloadingPackagesProgress { get; }
+
+ /// <summary>
+ /// Gets the downloading packages step status.
+ /// </summary>
+ String DownloadingPackagesStatus { get; }
+
+ /// <summary>
+ /// Occurs when the <see cref="CurrentStep"/> has changed.
+ /// </summary>
+ event EventHandler<MachineUpdateSteps> ProgressStep;
+
+ /// <summary>
+ /// Performs a machine update using the specified serial number and machine service address.
+ /// </summary>
+ /// <param name="serialNumber">The serial number.</param>
+ /// <param name="machineServiceAddress">The machine service address.</param>
+ /// <returns></returns>
+ Task<MachineUpdateResult> Update(String serialNumber, String machineServiceAddress);
+
+ /// <summary>
+ /// Checks if any update are available for the specified machine serial number.
+ /// </summary>
+ /// <param name="serialNumber">The serial number.</param>
+ /// <param name="machineServiceAddress">The machine service address.</param>
+ /// <returns></returns>
+ Task<CheckForUpdateResponse> CheckForUpdate(String serialNumber, String machineServiceAddress);
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
new file mode 100644
index 000000000..b86fb88d4
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
@@ -0,0 +1,287 @@
+using FluentFTP;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Tango.Core;
+using Tango.Core.DB;
+using Tango.Core.Helpers;
+using Tango.Core.IO;
+using Tango.PMR.Synchronization;
+using Tango.PPC.Common.Application;
+using Tango.Settings;
+using Tango.SQLExaminer;
+using Tango.Transport.Web;
+
+namespace Tango.PPC.Common.MachineUpdate
+{
+ public class MachineUpdateManager : ExtendedObject, IMachineUpdateManager
+ {
+ private IPPCApplicationManager _app_manager;
+
+ #region Events
+
+ /// <summary>
+ /// Occurs when there is a text log message available.
+ /// </summary>
+ public event EventHandler<string> ProgressLog;
+
+ /// <summary>
+ /// Occurs when the <see cref="CurrentStep" /> has changed.
+ /// </summary>
+ public event EventHandler<MachineUpdateSteps> ProgressStep;
+
+ #endregion
+
+ #region Properties
+
+ private MachineUpdateSteps _currentStep;
+ /// <summary>
+ /// Gets the current setup step.
+ /// </summary>
+ public MachineUpdateSteps CurrentStep
+ {
+ get { return _currentStep; }
+ set
+ {
+ if (_currentStep != value)
+ {
+ _currentStep = value;
+ RaisePropertyChangedAuto();
+ ProgressStep?.Invoke(this, _currentStep);
+ LogManager.Log("Machine Setup Manager Step: " + value.ToString());
+ }
+ }
+ }
+
+ private double _downloadProgress;
+ /// <summary>
+ /// Gets the downloading packages step progress.
+ /// </summary>
+ public double DownloadingPackagesProgress
+ {
+ get { return _downloadProgress; }
+ private set { _downloadProgress = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _updatingPackagesStatus;
+ /// <summary>
+ /// Gets the downloading packages step status.
+ /// </summary>
+ public String DownloadingPackagesStatus
+ {
+ get { return _updatingPackagesStatus; }
+ set { _updatingPackagesStatus = value; RaisePropertyChangedAuto(); }
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MachineUpdateManager"/> class.
+ /// </summary>
+ /// <param name="applicationManager">The application manager.</param>
+ public MachineUpdateManager(IPPCApplicationManager applicationManager)
+ {
+ _app_manager = applicationManager;
+ }
+
+ #region Public Methods
+
+ /// <summary>
+ /// Performs a machine setup using the specified serial number and machine service address.
+ /// </summary>
+ /// <param name="serialNumber">The serial number.</param>
+ /// <param name="machineServiceAddress">The machine service address.</param>
+ /// <returns></returns>
+ public Task<MachineUpdateResult> Update(string serialNumber, string machineServiceAddress)
+ {
+ return Task.Factory.StartNew<MachineUpdateResult>(() =>
+ {
+
+ LogManager.Log($"Starting machine update for serial number {serialNumber}...");
+
+ //Connect to machine service and get matching packages for this machine.
+ CurrentStep = MachineUpdateSteps.DownloadingPackage;
+ DownloadingPackagesProgress = 0;
+ DownloadingPackagesStatus = "Connecting to machine service...";
+
+ LogManager.Log($"Connecting to machine service on {machineServiceAddress}...");
+
+ DownloadUpdateRequest request = new DownloadUpdateRequest();
+ request.SerialNumber = serialNumber;
+
+ DownloadUpdateResponse update_response = null;
+
+ using (var http = new ProtoWebClient())
+ {
+ update_response = http.Post<DownloadUpdateRequest, DownloadUpdateResponse>(machineServiceAddress + "/api/Synchronization/MachineUpdate", request).Result;
+ }
+
+ 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.
+ var tempFile = TemporaryManager.CreateFile(".zip");
+
+ LogManager.Log($"Temporary package zip file created: {tempFile}.");
+
+ DownloadingPackagesStatus = "Downloading software package...";
+
+ LogManager.Log("Downloading software package...");
+
+ int fileSize = 0;
+ DownloadingPackagesProgress = 0;
+
+ using (FileStreamWrapper fs = new FileStreamWrapper(tempFile.Path, FileMode.Create, (current) =>
+ {
+ InvokeUINow(() =>
+ {
+ Thread.Sleep(2); //TODO: this is necessary only for visibility...
+ DownloadingPackagesProgress = ((double)current / (double)fileSize) * 100d;
+ });
+ }))
+ {
+ using (FtpClient ftp = new FtpClient(update_response.FtpAddress, update_response.FtpUserName, update_response.FtpPassword))
+ {
+ LogManager.Log("FTP: Connecting to site: " + update_response.FtpAddress);
+ ftp.ConnectAsync().Wait();
+ LogManager.Log("FTP: Retrieving download size...");
+ fileSize = (int)ftp.GetFileSize(update_response.FtpFilePath);
+ LogManager.Log("FTP: Download size: " + fileSize + " bytes.");
+ LogManager.Log("FTP: Starting download...");
+ ftp.DownloadAsync(fs, update_response.FtpFilePath).Wait();
+ }
+ }
+
+ LogManager.Log("Extracting downloaded zip file...");
+ //Extract software package.
+ ZipFile.ExtractToDirectory(tempFile, _newPackageTempFolder);
+
+
+ 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);
+
+
+ //Synchronize database
+ CurrentStep = MachineUpdateSteps.SynchronizingSchema;
+
+ String db_name = "Tango";
+ String localAddress = SettingsManager.Default.GetOrCreate<CoreSettings>().DataSource.Address;
+ String remote_address = update_response.DbAddress;
+
+ LogManager.Log($"Synchronizing database '{remote_address}\\{db_name}' => '{localAddress}\\{db_name}'...");
+
+ LogManager.Log("Initializing database manager...");
+ DbManager db = DbManager.FromAddressAndName(localAddress, db_name);
+
+ LogManager.Log("Checking Tango database exists on the local machine...");
+ if (!db.Exists(db_name))
+ {
+ throw new InvalidProgramException("Database tango does not exists.");
+ }
+
+ LogManager.Log("Disposing database manager.");
+ db.Dispose();
+
+ LogManager.Log($"Initializing {nameof(ExaminerSequenceConfigurationRunner)}...");
+
+ ExaminerSequenceConfigurationRunner runner = new ExaminerSequenceConfigurationRunner(
+ Path.Combine(_newPackageTempFolder, "Update Scripts", "config.xml"),
+ Path.Combine(_newPackageTempFolder, "Update Scripts"),
+ new ExaminerSequenceDataSource()
+ {
+ Address = remote_address,
+ DataBaseName = db_name,
+ IntegratedSecurity = false,
+ UserName = update_response.DbUserName,
+ Password = update_response.DbPassword,
+ },
+ new ExaminerSequenceDataSource()
+ {
+ Address = localAddress,
+ DataBaseName = db_name,
+ IntegratedSecurity = true,
+ }, serialNumber);
+
+ runner.Log += (x, msg) =>
+ {
+ LogManager.Log(msg);
+ ProgressLog?.Invoke(this, msg);
+ };
+
+ runner.ScriptExecuting += (x, item) =>
+ {
+ LogManager.Log($"Executing script {item.ToString()}...");
+
+ if (item.Type == ExaminerSequenceItemType.Data && item.RequiresSerialNumber)
+ {
+ CurrentStep = MachineUpdateSteps.SynchronizingMachineConfiguration;
+ }
+ else if (item.Type == ExaminerSequenceItemType.Data)
+ {
+ CurrentStep = MachineUpdateSteps.SynchronizingData;
+ }
+ };
+
+ LogManager.Log("Starting synchronization process...");
+
+ try
+ {
+ runner.Run().Wait();
+ LogManager.Log("Synchronization completed successfully!");
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Setup manager error while trying to synchronize database.");
+ }
+
+ return new MachineUpdateResult()
+ {
+ UpdatePackagePath = _newPackageTempFolder,
+ };
+ });
+ }
+
+ /// <summary>
+ /// Checks if any update are available for the specified machine serial number.
+ /// </summary>
+ /// <param name="serialNumber">The serial number.</param>
+ /// <param name="machineServiceAddress">The machine service address.</param>
+ /// <returns></returns>
+ public Task<CheckForUpdateResponse> CheckForUpdate(string serialNumber, string machineServiceAddress)
+ {
+ return Task.Factory.StartNew<CheckForUpdateResponse>(() =>
+ {
+ LogManager.Log($"Connecting to machine service on {machineServiceAddress}...");
+ LogManager.Log($"Checking if updates available...");
+
+ CheckForUpdateRequest request = new CheckForUpdateRequest();
+ request.SerialNumber = serialNumber;
+ request.Version = _app_manager.Version.ToString();
+
+ CheckForUpdateResponse update_response = null;
+
+ using (var http = new ProtoWebClient())
+ {
+ update_response = http.Post<CheckForUpdateRequest, CheckForUpdateResponse>(machineServiceAddress + "/api/Synchronization/CheckForUpdate", request).Result;
+ }
+
+ LogManager.Log($"Check for update response received: {Environment.NewLine}{update_response.ToJsonString()}");
+
+ return update_response;
+ });
+ }
+
+ #endregion
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs
new file mode 100644
index 000000000..17ae394ee
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Common.MachineUpdate
+{
+ public class MachineUpdateResult
+ {
+ /// <summary>
+ /// Gets or sets the temporary update package path from which to get the last downloaded software version.
+ /// </summary>
+ public String UpdatePackagePath { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateSteps.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateSteps.cs
new file mode 100644
index 000000000..3d8208e4b
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateSteps.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Common.MachineUpdate
+{
+ public enum MachineUpdateSteps
+ {
+ [Description("Downloading Package")]
+ DownloadingPackage,
+ [Description("Synchronizing Schema")]
+ SynchronizingSchema,
+ [Description("Synchronizing Data")]
+ SynchronizingData,
+ [Description("Updating Configuration")]
+ SynchronizingMachineConfiguration
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/NavigationView.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/NavigationView.cs
index 3c6d91502..ef8f1c2ad 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/NavigationView.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/NavigationView.cs
@@ -15,6 +15,7 @@ namespace Tango.PPC.Common.Navigation
LayoutView,
LoginView,
MachineSetupView,
+ MachineUpdateView,
ExternalBridgeView,
HomeModule,
ShutdownView,
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 0fbfb635e..35a79d497 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
@@ -126,6 +126,10 @@
<Compile Include="MachineSetup\MachineSetupManager.cs" />
<Compile Include="MachineSetup\MachineSetupResult.cs" />
<Compile Include="MachineSetup\MachineSetupSteps.cs" />
+ <Compile Include="MachineUpdate\IMachineUpdateManager.cs" />
+ <Compile Include="MachineUpdate\MachineUpdateManager.cs" />
+ <Compile Include="MachineUpdate\MachineUpdateResult.cs" />
+ <Compile Include="MachineUpdate\MachineUpdateSteps.cs" />
<Compile Include="Messages\JobRemovedMessage.cs" />
<Compile Include="Messages\JobSavedMessage.cs" />
<Compile Include="Messages\MachineSettingsSavedMessage.cs" />
@@ -299,7 +303,7 @@
</Target>
<ProjectExtensions>
<VisualStudio>
- <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" />
+ <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" />
</VisualStudio>
</ProjectExtensions>
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindow.xaml b/Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindow.xaml
index d1921b0a8..8e9b31dff 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindow.xaml
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindow.xaml
@@ -8,7 +8,7 @@
xmlns:examiner="clr-namespace:Tango.SQLExaminer;assembly=Tango.SQLExaminer"
xmlns:local="clr-namespace:Tango.PPC.Publisher"
mc:Ignorable="d"
- Title="Tango PPC Publisher" Height="800" Width="500" d:DataContext="{d:DesignInstance Type=local:MainWindowVM, IsDesignTimeCreatable=False}">
+ Title="Tango PPC Publisher" Height="980" Width="500" d:DataContext="{d:DesignInstance Type=local:MainWindowVM, IsDesignTimeCreatable=False}">
<Window.Resources>
<converters:EnumToItemsSourceConverter x:Key="EnumToItemsSourceConverter" />
@@ -53,9 +53,22 @@
</TextBlock>
</TextBlock>
- <TextBlock Margin="0 20 0 0">Examiner Sequence Items</TextBlock>
+ <TextBlock Margin="0 20 0 0">Examiner Provision Sequence Items</TextBlock>
- <DataGrid Height="200" SelectionMode="Single" SelectionUnit="FullRow" HorizontalScrollBarVisibility="Disabled" AutoGenerateColumns="False" ItemsSource="{Binding SequenceItems}" CanUserAddRows="True" CanUserReorderColumns="False" CanUserDeleteRows="True" CanUserSortColumns="False" AddingNewItem="DataGrid_AddingNewItem">
+ <DataGrid Height="170" SelectionMode="Single" SelectionUnit="FullRow" HorizontalScrollBarVisibility="Disabled" AutoGenerateColumns="False" ItemsSource="{Binding ProvisionSequenceItemsView}" CanUserAddRows="True" CanUserReorderColumns="False" CanUserDeleteRows="True" CanUserSortColumns="False" AddingNewItem="DataGrid_AddingNewItem">
+ <DataGrid.Columns>
+ <DataGridTextColumn IsReadOnly="True" Width="100" Header="File Name" Binding="{Binding FileName}" />
+ <DataGridComboBoxColumn Width="75" Header="Type" ItemsSource="{Binding Source={x:Type examiner:ExaminerSequenceItemType},Converter={StaticResource EnumToItemsSourceConverter}}" SelectedValueBinding="{Binding Type}" SelectedValuePath="Value" DisplayMemberPath="DisplayName" />
+ <DataGridComboBoxColumn Width="90" Header="Direction" ItemsSource="{Binding Source={x:Type examiner:ExaminerSequenceItemDirection},Converter={StaticResource EnumToItemsSourceConverter}}" SelectedValueBinding="{Binding Direction}" SelectedValuePath="Value" DisplayMemberPath="DisplayName" />
+ <DataGridCheckBoxColumn Width="35" Header="S/N" Binding="{Binding RequiresSerialNumber}" />
+ <DataGridTextColumn Header="Name" Width="1*" Binding="{Binding Name}" />
+ <DataGridTextColumn Header="Index" Width="40" Binding="{Binding Index}" />
+ </DataGrid.Columns>
+ </DataGrid>
+
+ <TextBlock Margin="0 20 0 0">Examiner Update Sequence Items</TextBlock>
+
+ <DataGrid Height="170" SelectionMode="Single" SelectionUnit="FullRow" HorizontalScrollBarVisibility="Disabled" AutoGenerateColumns="False" ItemsSource="{Binding UpdateSequenceItemsView}" CanUserAddRows="True" CanUserReorderColumns="False" CanUserDeleteRows="True" CanUserSortColumns="False" AddingNewItem="DataGrid_AddingNewItem_1">
<DataGrid.Columns>
<DataGridTextColumn IsReadOnly="True" Width="100" Header="File Name" Binding="{Binding FileName}" />
<DataGridComboBoxColumn Width="75" Header="Type" ItemsSource="{Binding Source={x:Type examiner:ExaminerSequenceItemType},Converter={StaticResource EnumToItemsSourceConverter}}" SelectedValueBinding="{Binding Type}" SelectedValuePath="Value" DisplayMemberPath="DisplayName" />
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindow.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindow.xaml.cs
index 64e7e8740..610eb40a8 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindow.xaml.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindow.xaml.cs
@@ -1,6 +1,7 @@
using Microsoft.Win32;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -13,6 +14,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
+using Tango.SQLExaminer;
namespace Tango.PPC.Publisher
{
@@ -35,9 +37,54 @@ namespace Tango.PPC.Publisher
{
SequenceItem item = new SequenceItem();
- if ((DataContext as MainWindowVM).SequenceItems.Count > 0)
+ var config = ExaminerConfiguration.FromFile(dlg.FileName);
+
+ if (config.Maker == "SQL Examiner")
+ {
+ item.Type = ExaminerSequenceItemType.Schema;
+ }
+ else
+ {
+ item.Type = ExaminerSequenceItemType.Data;
+ }
+
+ item.RequiresSerialNumber = File.ReadAllText(dlg.FileName).Contains("'@'");
+
+ if ((DataContext as MainWindowVM).ProvisionSequenceItems.Count > 0)
+ {
+ item.Index = (DataContext as MainWindowVM).ProvisionSequenceItems.Max(x => x.Index + 1);
+ }
+ item.FilePath = dlg.FileName;
+ item.Name = System.IO.Path.GetFileNameWithoutExtension(dlg.FileName);
+
+ e.NewItem = item;
+ }
+ }
+
+ private void DataGrid_AddingNewItem_1(object sender, AddingNewItemEventArgs e)
+ {
+ OpenFileDialog dlg = new OpenFileDialog();
+ dlg.Filter = "SQL Examiner Configuration|*.xml";
+ if (dlg.ShowDialog().Value)
+ {
+ SequenceItem item = new SequenceItem();
+
+ var config = ExaminerConfiguration.FromFile(dlg.FileName);
+
+ if (config.Maker == "SQL Examiner")
+ {
+ item.Type = ExaminerSequenceItemType.Schema;
+ }
+ else
+ {
+ item.Type = ExaminerSequenceItemType.Data;
+ }
+
+ item.RequiresSerialNumber = File.ReadAllText(dlg.FileName).Contains("'@'");
+
+ if ((DataContext as MainWindowVM).UpdateSequenceItems.Count > 0)
{
- item.Index = (DataContext as MainWindowVM).SequenceItems.Max(x => x.Index + 1);
+ item.Index = (DataContext as MainWindowVM).UpdateSequenceItems.Max(x => x.Index + 1);
}
item.FilePath = dlg.FileName;
item.Name = System.IO.Path.GetFileNameWithoutExtension(dlg.FileName);
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindowVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindowVM.cs
index 48e4fdf01..4828879e1 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindowVM.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Publisher/MainWindowVM.cs
@@ -66,27 +66,35 @@ namespace Tango.PPC.Publisher
set { _currentVersion = value; RaisePropertyChangedAuto(); }
}
- private ObservableCollection<SequenceItem> _sequenceItems;
- public ObservableCollection<SequenceItem> SequenceItems
+ private ObservableCollection<SequenceItem> _provisionSequenceItems;
+ public ObservableCollection<SequenceItem> ProvisionSequenceItems
{
- get { return _sequenceItems; }
- set { _sequenceItems = value; RaisePropertyChangedAuto(); }
+ get { return _provisionSequenceItems; }
+ set { _provisionSequenceItems = value; RaisePropertyChangedAuto(); }
}
- private ICollectionView _sequenceItemsView;
- public ICollectionView SequenceItemsView
+ private ICollectionView _provisionSequenceItemsView;
+ public ICollectionView ProvisionSequenceItemsView
{
- get { return _sequenceItemsView; }
- set { _sequenceItemsView = value; RaisePropertyChangedAuto(); }
+ get { return _provisionSequenceItemsView; }
+ set { _provisionSequenceItemsView = value; RaisePropertyChangedAuto(); }
}
- private SequenceItem _selectedSequenceItem;
- public SequenceItem SelectedSequenceItem
+ private ObservableCollection<SequenceItem> _updateSequenceItems;
+ public ObservableCollection<SequenceItem> UpdateSequenceItems
{
- get { return _selectedSequenceItem; }
- set { _selectedSequenceItem = value; RaisePropertyChangedAuto(); }
+ get { return _updateSequenceItems; }
+ set { _updateSequenceItems = value; RaisePropertyChangedAuto(); }
}
+ private ICollectionView _updateSequenceItemsView;
+ public ICollectionView UpdateSequenceItemsView
+ {
+ get { return _updateSequenceItemsView; }
+ set { _updateSequenceItemsView = value; RaisePropertyChangedAuto(); }
+ }
+
+
private String _email;
public String Email
{
@@ -137,10 +145,13 @@ namespace Tango.PPC.Publisher
_hashGenerator = new BasicHashGenerator();
- SequenceItems = new ObservableCollection<SequenceItem>();
- SequenceItemsView = CollectionViewSource.GetDefaultView(SequenceItems);
+ ProvisionSequenceItems = new ObservableCollection<SequenceItem>();
+ ProvisionSequenceItemsView = CollectionViewSource.GetDefaultView(ProvisionSequenceItems);
+ ProvisionSequenceItemsView.SortDescriptions.Add(new SortDescription(nameof(SequenceItem.Index), ListSortDirection.Ascending));
- SequenceItemsView.SortDescriptions.Add(new SortDescription(nameof(SequenceItem.Index), ListSortDirection.Ascending));
+ UpdateSequenceItems = new ObservableCollection<SequenceItem>();
+ UpdateSequenceItemsView = CollectionViewSource.GetDefaultView(UpdateSequenceItems);
+ UpdateSequenceItemsView.SortDescriptions.Add(new SortDescription(nameof(SequenceItem.Index), ListSortDirection.Ascending));
using (ObservablesContext db = ObservablesContext.CreateDefault("twine01\\SQLTWINE_TEST"))
{
@@ -196,15 +207,44 @@ namespace Tango.PPC.Publisher
using (ZipFile zip = new ZipFile())
{
- String sync_dir = "Synchronization Scripts";
+ String provision_dir = "Provision Scripts";
+
+ zip.AddDirectoryByName(provision_dir);
+
+ ExaminerSequenceConfiguration provision_config = new ExaminerSequenceConfiguration();
+
+ foreach (var item in ProvisionSequenceItems)
+ {
+ provision_config.Items.Add(new ExaminerSequenceItem()
+ {
+ Direction = item.Direction,
+ FileName = item.FileName,
+ Index = item.Index,
+ Name = item.Name,
+ Type = item.Type,
+ RequiresSerialNumber = item.RequiresSerialNumber
+ });
+
+ zip.AddFile(item.FilePath, provision_dir);
+ }
+
+ String provision_config_file = TemporaryManager.Default.CreateFile(".zip");
+ provision_config.ToFile(provision_config_file);
+
+ var cf = zip.AddFile(provision_config_file, provision_dir);
+ cf.FileName = provision_dir + "\\config.xml";
+
+
+
+ String update_dir = "Update Scripts";
- zip.AddDirectoryByName(sync_dir);
+ zip.AddDirectoryByName(update_dir);
- ExaminerSequenceConfiguration config = new ExaminerSequenceConfiguration();
+ ExaminerSequenceConfiguration update_config = new ExaminerSequenceConfiguration();
- foreach (var item in SequenceItems)
+ foreach (var item in UpdateSequenceItems)
{
- config.Items.Add(new ExaminerSequenceItem()
+ update_config.Items.Add(new ExaminerSequenceItem()
{
Direction = item.Direction,
FileName = item.FileName,
@@ -214,14 +254,14 @@ namespace Tango.PPC.Publisher
RequiresSerialNumber = item.RequiresSerialNumber
});
- zip.AddFile(item.FilePath, sync_dir);
+ zip.AddFile(item.FilePath, update_dir);
}
- String config_file = TemporaryManager.Default.CreateFile(".zip");
- config.ToFile(config_file);
+ String update_config_file = TemporaryManager.Default.CreateFile(".zip");
+ update_config.ToFile(update_config_file);
- var cf = zip.AddFile(config_file, sync_dir);
- cf.FileName = sync_dir + "\\config.xml";
+ var cuf = zip.AddFile(update_config_file, update_dir);
+ cuf.FileName = update_dir + "\\config.xml";
foreach (var file in Directory.GetFiles(_appPath, "*.*", SearchOption.TopDirectoryOnly))
{
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/machine-update.png b/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/machine-update.png
new file mode 100644
index 000000000..3e49520dd
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/machine-update.png
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/right-arrow-64.png b/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/right-arrow-64.png
new file mode 100644
index 000000000..b23d81f3c
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/right-arrow-64.png
Binary files differ
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 e43f37e5f..714b83dfa 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs
@@ -71,7 +71,6 @@ namespace Tango.PPC.UI.PPCApplication
/// <summary>
/// Gets the application version.
/// </summary>
- /// <exception cref="NotImplementedException"></exception>
public Version Version
{
get
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Properties/AssemblyInfo.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Properties/AssemblyInfo.cs
index 648ddbb59..a4ffefec8 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Properties/AssemblyInfo.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Properties/AssemblyInfo.cs
@@ -7,5 +7,5 @@ using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
-[assembly: AssemblyTitle("Tango Panel PC Application")]
+[assembly: AssemblyTitle("Tango PPC Application")]
[assembly: AssemblyVersion("2.0.7.1119")]
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj
index 2b2752a24..fc4c94eb0 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj
@@ -134,8 +134,10 @@
<Compile Include="ViewModels\LoginViewVM.cs" />
<Compile Include="ViewModels\MachineSetupViewVM.cs" />
<Compile Include="ViewModels\MainViewVM.cs" />
+ <Compile Include="ViewModels\MachineUpdateViewVM.cs" />
<Compile Include="ViewsContracts\ILayoutView.cs" />
<Compile Include="ViewsContracts\IMachineSetupView.cs" />
+ <Compile Include="ViewsContracts\IMachineUpdateView.cs" />
<Compile Include="Views\ExternalBridgeView.xaml.cs">
<DependentUpon>ExternalBridgeView.xaml</DependentUpon>
</Compile>
@@ -154,6 +156,9 @@
<Compile Include="Views\MainView.xaml.cs">
<DependentUpon>MainView.xaml</DependentUpon>
</Compile>
+ <Compile Include="Views\MachineUpdateView.xaml.cs">
+ <DependentUpon>MachineUpdateView.xaml</DependentUpon>
+ </Compile>
<Page Include="Connectivity\WiFiAuthenticationView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -206,6 +211,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="Views\MachineUpdateView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
@@ -356,6 +365,8 @@
<Link>Tango.ColorLib.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Resource Include="Images\right-arrow-64.png" />
+ <Resource Include="Images\machine-update.png" />
<Resource Include="Images\home.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
@@ -421,7 +432,7 @@ copy /Y "$(SolutionDir)Referenced Assemblies\vcruntime140d.dll" "$(TargetDir)"</
</PropertyGroup>
<ProjectExtensions>
<VisualStudio>
- <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" />
+ <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" />
</VisualStudio>
</ProjectExtensions>
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs
index bec1d2b48..57fae7791 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs
@@ -11,6 +11,7 @@ using Tango.PPC.Common.Diagnostics;
using Tango.PPC.Common.EventLogging;
using Tango.PPC.Common.ExternalBridge;
using Tango.PPC.Common.MachineSetup;
+using Tango.PPC.Common.MachineUpdate;
using Tango.PPC.Common.Modules;
using Tango.PPC.Common.Navigation;
using Tango.PPC.Common.Notifications;
@@ -55,6 +56,7 @@ namespace Tango.PPC.UI
TangoIOC.Default.Unregister<ITeamFoundationServiceClient>();
TangoIOC.Default.Unregister<IPPCExternalBridgeService>();
TangoIOC.Default.Unregister<IMachineSetupManager>();
+ TangoIOC.Default.Unregister<IMachineUpdateManager>();
TangoIOC.Default.Unregister<IPrintingManager>();
TangoIOC.Default.Unregister<IConnectivityProvider>();
@@ -70,6 +72,7 @@ namespace Tango.PPC.UI
TangoIOC.Default.Register<IEventLogger, DefaultEventLogger>();
TangoIOC.Default.Register<IPPCExternalBridgeService, PPCExternalBridgeService>();
TangoIOC.Default.Register<IMachineSetupManager, MachineSetupManager>();
+ TangoIOC.Default.Register<IMachineUpdateManager, MachineUpdateManager>();
TangoIOC.Default.Register<IPrintingManager, DefaultPrintingManager>();
TangoIOC.Default.Register<IConnectivityProvider, DefaultConnectivityProvider>();
@@ -81,12 +84,14 @@ namespace Tango.PPC.UI
TangoIOC.Default.Register<LayoutViewVM>();
TangoIOC.Default.Register<ExternalBridgeViewVM>();
TangoIOC.Default.Register<MachineSetupViewVM>();
+ TangoIOC.Default.Register<MachineUpdateViewVM>();
TangoIOC.Default.GetInstance<IPPCApplicationManager>().ContentRendered += (_, __) =>
{
TangoIOC.Default.Register<ILayoutView, LayoutView>(LayoutView.Instance);
TangoIOC.Default.Register<IMachineSetupView, MachineSetupView>(MachineSetupView.Instance);
+ TangoIOC.Default.Register<IMachineUpdateView, MachineUpdateView>(MachineUpdateView.Instance);
};
//TangoIOC.Default.Register<LoadingViewVM>();
@@ -145,5 +150,13 @@ namespace Tango.PPC.UI
return TangoIOC.Default.GetInstance<MachineSetupViewVM>();
}
}
+
+ public static MachineUpdateViewVM MachineUpdateViewVM
+ {
+ get
+ {
+ return TangoIOC.Default.GetInstance<MachineUpdateViewVM>();
+ }
+ }
}
} \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/LayoutViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/LayoutViewVM.cs
index 28692cdfa..fd36d0d13 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/LayoutViewVM.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/LayoutViewVM.cs
@@ -84,6 +84,10 @@ namespace Tango.PPC.UI.ViewModels
/// </summary>
public RelayCommand SignOutCommand { get; set; }
+ /// <summary>
+ /// Gets or sets the update command.
+ /// </summary>
+ public RelayCommand UpdateCommand { get; set; }
#endregion
#region Constructors
@@ -100,6 +104,11 @@ namespace Tango.PPC.UI.ViewModels
StopPrintingCommand = new RelayCommand(StopPrinting);
SignOutCommand = new RelayCommand(SignOut);
+ UpdateCommand = new RelayCommand(() =>
+ {
+ NavigationManager.NavigateTo(NavigationView.MachineUpdateView);
+ TangoIOC.Default.GetInstance<MachineUpdateViewVM>().CheckForUpdates();
+ });
}
#endregion
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineSetupViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineSetupViewVM.cs
index 0f66b6fc8..f3cb83ffe 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineSetupViewVM.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineSetupViewVM.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Diagnostics;
+using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -227,11 +228,11 @@ namespace Tango.PPC.UI.ViewModels
/// </summary>
private void CompleteSetup()
{
- String updater_exe = AssemblyHelper.GetCurrentAssemblyFolder() + "\\Tango.PPC.Updater.exe";
+ String updater_exe = Path.Combine(_setup_result.UpdatePackagePath, "Tango.PPC.Updater.exe");
LogManager.Log("Completing machine setup...");
- LogManager.Log($"Executing '{updater_exe}' with arguments '{_setup_result.UpdatePackagePath}'...");
- Process.Start(updater_exe, _setup_result.UpdatePackagePath);
+ LogManager.Log($"Executing '{updater_exe}' with arguments '{PathHelper.GetStartupPath()}'...");
+ Process.Start(updater_exe, PathHelper.GetStartupPath());
LogManager.Log("Terminating application process!");
Environment.Exit(0);
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs
new file mode 100644
index 000000000..84e65e516
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs
@@ -0,0 +1,170 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core.Commands;
+using Tango.Core.Helpers;
+using Tango.PPC.Common;
+using Tango.PPC.Common.MachineUpdate;
+using Tango.PPC.UI.ViewsContracts;
+
+namespace Tango.PPC.UI.ViewModels
+{
+ public class MachineUpdateViewVM : PPCViewModel<IMachineUpdateView>
+ {
+ public enum MachineUpdateView
+ {
+
+ UpdateCheckView,
+ UpdateCheckErrorView,
+ UpdateAvailableView,
+ UpToDateView,
+ UpdateProgressView,
+ UpdateCompletedView,
+ UpdateFailedView,
+ }
+
+ private MachineUpdateResult _update_result;
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the machine update manager.
+ /// </summary>
+ public IMachineUpdateManager MachineUpdateManager { get; set; }
+
+ private String _latestVersion;
+ /// <summary>
+ /// Gets or sets the latest version.
+ /// </summary>
+ public String LatestVersion
+ {
+ get { return _latestVersion; }
+ set { _latestVersion = value; RaisePropertyChangedAuto(); }
+ }
+
+ #endregion
+
+ #region Commands
+
+ /// <summary>
+ /// Gets or sets the complete command.
+ /// </summary>
+ public RelayCommand CompleteCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the install command.
+ /// </summary>
+ public RelayCommand UpdateCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the restart command.
+ /// </summary>
+ public RelayCommand RestartCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the close command.
+ /// </summary>
+ public RelayCommand CloseCommand { get; set; }
+
+ #endregion
+
+ #region Constructors
+
+ public MachineUpdateViewVM(IMachineUpdateManager machineUpdateManager)
+ {
+ MachineUpdateManager = machineUpdateManager;
+
+ CompleteCommand = new RelayCommand(CompleteUpdate);
+ UpdateCommand = new RelayCommand(Update);
+ RestartCommand = new RelayCommand(CheckForUpdates);
+ CloseCommand = new RelayCommand(() =>
+ {
+ NavigationManager.NavigateTo(Common.Navigation.NavigationView.HomeModule);
+ NavigateTo(MachineUpdateView.UpdateCheckView);
+ });
+ }
+
+ #endregion
+
+ #region Update
+
+ public async void CheckForUpdates()
+ {
+ await NavigateTo(MachineUpdateView.UpdateCheckView);
+
+ try
+ {
+ var response = await MachineUpdateManager.CheckForUpdate(MachineProvider.Machine.SerialNumber, "http://localhost:51581/");
+
+ if (response.IsUpdateAvailable)
+ {
+ LatestVersion = response.Version;
+ await NavigateTo(MachineUpdateView.UpdateAvailableView);
+ }
+ else
+ {
+ await NavigateTo(MachineUpdateView.UpToDateView);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error while trying to check for updates.");
+ await NavigateTo(MachineUpdateView.UpdateFailedView);
+ }
+ }
+
+ private async void Update()
+ {
+ await NavigateTo(MachineUpdateView.UpdateProgressView);
+
+ LogManager.Log("Starting machine update...");
+
+ try
+ {
+ _update_result = await MachineUpdateManager.Update(MachineProvider.Machine.SerialNumber, "http://localhost:51581/");
+ LogManager.Log("Machine update completed.");
+ await NavigateTo(MachineUpdateView.UpdateCompletedView);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Machine update failed.");
+ await NavigateTo(MachineUpdateView.UpdateFailedView);
+ }
+ }
+
+ #endregion
+
+ #region Complete
+
+ private void CompleteUpdate()
+ {
+ String updater_exe = Path.Combine(_update_result.UpdatePackagePath, "Tango.PPC.Updater.exe");
+
+ LogManager.Log("Completing machine setup...");
+ LogManager.Log($"Executing '{updater_exe}' with arguments '{PathHelper.GetStartupPath()}'...");
+ Process.Start(updater_exe, PathHelper.GetStartupPath());
+ LogManager.Log("Terminating application process!");
+ Environment.Exit(0);
+ }
+
+ #endregion
+
+ public override void OnApplicationStarted()
+ {
+
+ }
+
+ /// <summary>
+ /// Navigates to the specified view.
+ /// </summary>
+ /// <param name="view">The view.</param>
+ private Task NavigateTo(MachineUpdateView view)
+ {
+ return View.NavigateTo(view);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml
index 19f2caa59..2db5f12b6 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml
@@ -60,6 +60,15 @@
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
+
+ <StackPanel Margin="0 5 0 0">
+ <touch:TouchButton Style="{StaticResource TangoFlatButton}" Padding="30" Foreground="{StaticResource TangoDarkForegroundBrush}" Command="{Binding UpdateCommand}" FontSize="{StaticResource TangoHeaderFontSize}">
+ <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
+ <Image Source="/Images/right-arrow-64.png" VerticalAlignment="Center" Width="48" Height="48"></Image>
+ <TextBlock VerticalAlignment="Center" Margin="20 0 0 0">Update</TextBlock>
+ </StackPanel>
+ </touch:TouchButton>
+ </StackPanel>
</StackPanel>
<!--<StackPanel DockPanel.Dock="Bottom">
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml
new file mode 100644
index 000000000..ce1cee424
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml
@@ -0,0 +1,129 @@
+<UserControl x:Class="Tango.PPC.UI.Views.MachineUpdateView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:global="clr-namespace:Tango.PPC.UI"
+ xmlns:update="clr-namespace:Tango.PPC.Common.MachineUpdate;assembly=Tango.PPC.Common"
+ xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
+ xmlns:connectivity="clr-namespace:Tango.PPC.Common.Connectivity;assembly=Tango.PPC.Common"
+ xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch"
+ xmlns:vm="clr-namespace:Tango.PPC.UI.ViewModels"
+ xmlns:local="clr-namespace:Tango.PPC.UI.Views"
+ mc:Ignorable="d"
+ d:DesignHeight="1280" d:DesignWidth="800" Background="{StaticResource TangoPrimaryBackgroundBrush}" d:DataContext="{d:DesignInstance Type=vm:MachineUpdateViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MachineUpdateViewVM}">
+ <Grid>
+ <DockPanel>
+
+ <StackPanel DockPanel.Dock="Top" HorizontalAlignment="Center" Margin="0 10 0 0">
+ <Image Source="/Images/machine-update.png" Stretch="None" />
+ </StackPanel>
+
+ <controls:NavigationControl x:Name="navigationControl" TransitionType="Slide" KeepElementsAttached="True" Margin="0 20 0 0" SelectedIndex="0">
+
+ <Grid controls:NavigationControl.NavigationName="UpdateCheckView">
+ <StackPanel HorizontalAlignment="Center" Margin="0 200 0 0">
+ <touch:TouchBusyIndicator Width="250" Height="250" IsIndeterminate="{Binding IsVisible}" />
+ <TextBlock DockPanel.Dock="Top" Margin="0 100" FontSize="{StaticResource TangoHeaderFontSize}" HorizontalAlignment="Center" TextWrapping="Wrap" TextAlignment="Center">
+ Checking for updates, please wait...
+ </TextBlock>
+ </StackPanel>
+ </Grid>
+
+ <Grid controls:NavigationControl.NavigationName="UpdateAvailableView">
+ <StackPanel HorizontalAlignment="Center" Margin="0 40 0 0">
+ <TextBlock FontSize="{StaticResource TangoHeaderFontSize}">
+ <Run>Version</Run>
+ <Run Foreground="{StaticResource TangoPrimaryAccentBrush}" Text="{Binding LatestVersion}"></Run>
+ <Run>is available</Run>
+ </TextBlock>
+
+ <TextBlock FontSize="{StaticResource TangoTitleFontSize}" Margin="0 40 0 0">
+ Updating you machine can improve the following:
+ </TextBlock>
+
+ <StackPanel Margin="0 40 0 0">
+ <StackPanel Orientation="Horizontal" TextElement.FontSize="{StaticResource TangoTitleFontSize}">
+ <touch:TouchIcon Width="24" Height="24" Icon="Check" Foreground="{StaticResource TangoPrimaryAccentBrush}" />
+ <TextBlock Margin="10 0 0 0" VerticalAlignment="Center">Support for new media</TextBlock>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Margin="0 10 0 0" TextElement.FontSize="{StaticResource TangoTitleFontSize}">
+ <touch:TouchIcon Width="24" Height="24" Icon="Check" Foreground="{StaticResource TangoPrimaryAccentBrush}" />
+ <TextBlock Margin="10 0 0 0" VerticalAlignment="Center">Refined color conversion and calibration algorithms</TextBlock>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Margin="0 10 0 0" TextElement.FontSize="{StaticResource TangoTitleFontSize}">
+ <touch:TouchIcon Width="24" Height="24" Icon="Check" Foreground="{StaticResource TangoPrimaryAccentBrush}" />
+ <TextBlock Margin="10 0 0 0" VerticalAlignment="Center">Software fixes and improvements</TextBlock>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Margin="0 10 0 0" TextElement.FontSize="{StaticResource TangoTitleFontSize}">
+ <touch:TouchIcon Width="24" Height="24" Icon="Check" Foreground="{StaticResource TangoPrimaryAccentBrush}" />
+ <TextBlock Margin="10 0 0 0" VerticalAlignment="Center">Firmware upgrade</TextBlock>
+ </StackPanel>
+ </StackPanel>
+
+ <TextBlock Margin="0 60 0 0" FontSize="{StaticResource TangoTitleFontSize}">
+ Tap 'UPDATE' to start updating now.
+ </TextBlock>
+
+ <touch:TouchButton Margin="0 200 0 0" Padding="20" Width="300" CornerRadius="35" Command="{Binding UpdateCommand}">UPDATE</touch:TouchButton>
+ </StackPanel>
+ </Grid>
+
+ <Grid controls:NavigationControl.NavigationName="UpToDateView">
+ <StackPanel HorizontalAlignment="Center" Margin="0 50 0 0">
+ <touch:TouchIcon Icon="Check" Foreground="{StaticResource TangoPrimaryAccentBrush}" Width="70" Height="70" />
+ <TextBlock VerticalAlignment="Center" Margin="0 10 0 0" Foreground="{StaticResource TangoPrimaryAccentBrush}" FontSize="{StaticResource TangoHeaderFontSize}">Your machine is up to date!</TextBlock>
+
+ <touch:TouchButton Margin="0 200 0 0" Padding="20" Width="300" CornerRadius="35" Command="{Binding CloseCommand}">CLOSE</touch:TouchButton>
+ </StackPanel>
+ </Grid>
+
+ <Grid controls:NavigationControl.NavigationName="UpdateCheckErrorView">
+ <StackPanel HorizontalAlignment="Center" Margin="0 50 0 0">
+ <touch:TouchIcon Icon="AlertOctagon" Foreground="{StaticResource TangoErrorBrush}" Width="70" Height="70" />
+ <TextBlock VerticalAlignment="Center" Width="600" TextWrapping="Wrap" TextAlignment="Center" Margin="0 10 0 0" Foreground="{StaticResource TangoErrorBrush}" FontSize="{StaticResource TangoTitleFontSize}">An error occurred while trying to check for updates. Please check your internet connection and try again.</TextBlock>
+
+ <touch:TouchButton Margin="0 200 0 0" Padding="20" Width="300" CornerRadius="35" Command="{Binding RestartCommand}">TRY AGAIN</touch:TouchButton>
+ </StackPanel>
+ </Grid>
+
+ <Grid controls:NavigationControl.NavigationName="UpdateProgressView">
+ <StackPanel>
+ <TextBlock HorizontalAlignment="Center" Margin="0 40 0 0" FontSize="{StaticResource TangoHeaderFontSize}">Updating your machine</TextBlock>
+ <TextBlock Margin="0 10 0 0" TextAlignment="Center" FontSize="{StaticResource TangoTitleFontSize}" Foreground="{StaticResource TangoGrayBrush}">Do not turn off the machine</TextBlock>
+
+ <touch:TouchBusyIndicator Width="100" Height="100" Margin="0 80 0 0" IsIndeterminate="{Binding IsVisible}"></touch:TouchBusyIndicator>
+ <touch:TouchStepProgressBar FontSize="10" Width="720" Height="50" Margin="0 100 0 0" ItemsSource="{Binding Source={x:Type update:MachineUpdateSteps},Converter={StaticResource EnumToItemsSourceConverter}}" SelectedValue="{Binding MachineUpdateManager.CurrentStep}" SelectedValuePath="Value" DisplayMemberPath="DisplayName" />
+
+ <StackPanel Margin="100 100 100 0" Visibility="{Binding MachineUpdateManager.CurrentStep,Converter={StaticResource EnumToVisibilityConverter},ConverterParameter='DownloadingPackage'}">
+ <TextBlock Text="{Binding MachineUpdateManager.DownloadingPackagesStatus,Mode=OneWay}"></TextBlock>
+ <touch:TouchProgressBar Margin="0 10 0 0" Height="10" Maximum="100" Value="{Binding MachineUpdateManager.DownloadingPackagesProgress,Mode=OneWay}" />
+ </StackPanel>
+ </StackPanel>
+ </Grid>
+
+ <Grid controls:NavigationControl.NavigationName="UpdateCompletedView">
+ <StackPanel HorizontalAlignment="Center" Margin="0 50 0 0">
+ <touch:TouchIcon Icon="Check" Foreground="{StaticResource TangoPrimaryAccentBrush}" Width="70" Height="70" />
+ <TextBlock VerticalAlignment="Center" Margin="0 10 0 0" Foreground="{StaticResource TangoPrimaryAccentBrush}" FontSize="{StaticResource TangoHeaderFontSize}">Update completed successfully !</TextBlock>
+
+ <touch:TouchButton Margin="0 200 0 0" Padding="20" Width="300" CornerRadius="35" Command="{Binding CompleteCommand}">RESTART</touch:TouchButton>
+ </StackPanel>
+ </Grid>
+
+ <Grid controls:NavigationControl.NavigationName="UpdateFailedView">
+ <StackPanel HorizontalAlignment="Center" Margin="0 50 0 0">
+ <touch:TouchIcon Icon="AlertOctagon" Foreground="{StaticResource TangoErrorBrush}" Width="70" Height="70" />
+ <TextBlock VerticalAlignment="Center" Margin="0 10 0 0" Foreground="{StaticResource TangoErrorBrush}" FontSize="{StaticResource TangoTitleFontSize}">An error occurred while trying to update the machine.</TextBlock>
+
+ <touch:TouchButton Margin="0 200 0 0" Padding="20" Width="300" CornerRadius="35" Command="{Binding RestartCommand}">TRY AGAIN</touch:TouchButton>
+ </StackPanel>
+ </Grid>
+
+ </controls:NavigationControl>
+ </DockPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml.cs
new file mode 100644
index 000000000..f63899932
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml.cs
@@ -0,0 +1,46 @@
+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;
+using Tango.PPC.UI.ViewModels;
+using Tango.PPC.UI.ViewsContracts;
+
+namespace Tango.PPC.UI.Views
+{
+ /// <summary>
+ /// Interaction logic for UpdateView.xaml
+ /// </summary>
+ public partial class MachineUpdateView : UserControl, IMachineUpdateView
+ {
+ public MachineUpdateView()
+ {
+ InitializeComponent();
+
+ Instance = this;
+ }
+
+ public static MachineUpdateView Instance { get; internal set; }
+
+ public Task NavigateTo(MachineUpdateViewVM.MachineUpdateView view)
+ {
+ TaskCompletionSource<object> source = new TaskCompletionSource<object>();
+
+ navigationControl.NavigateTo(view.ToString(), () =>
+ {
+ source.SetResult(new object());
+ });
+
+ return source.Task;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MainView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MainView.xaml
index 9e47bfcdb..8e54f0990 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MainView.xaml
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MainView.xaml
@@ -45,6 +45,7 @@
<local:LayoutView></local:LayoutView>
<local:ExternalBridgeView></local:ExternalBridgeView>
<local:MachineSetupView></local:MachineSetupView>
+ <local:MachineUpdateView></local:MachineUpdateView>
</controls:NavigationControl>
</touch:TouchPanel>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewsContracts/IMachineUpdateView.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewsContracts/IMachineUpdateView.cs
new file mode 100644
index 000000000..d71822b11
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewsContracts/IMachineUpdateView.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.PPC.Common;
+using static Tango.PPC.UI.ViewModels.MachineUpdateViewVM;
+
+namespace Tango.PPC.UI.ViewsContracts
+{
+ public interface IMachineUpdateView : IPPCView
+ {
+ /// <summary>
+ /// Navigates to the specified machine setup view.
+ /// </summary>
+ /// <param name="view">The view.</param>
+ Task NavigateTo(MachineUpdateView view);
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Updater/MainWindow.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.Updater/MainWindow.xaml.cs
index 394d3292f..55c60058b 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Updater/MainWindow.xaml.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Updater/MainWindow.xaml.cs
@@ -23,9 +23,9 @@ namespace Tango.PPC.Updater
/// </summary>
public partial class MainWindow : Window
{
- private String _appPath = AppDomain.CurrentDomain.BaseDirectory;
+ private String _sourceFolder = AppDomain.CurrentDomain.BaseDirectory;
private String _msProcessName = "Tango.PPC.UI";
- private String _sourceFolder = App.StartupArgs.FirstOrDefault();
+ private String _appPath = String.Join(" ", App.StartupArgs);
public MainWindow()
{
@@ -37,7 +37,7 @@ namespace Tango.PPC.Updater
// }
//#endif
- if (!Directory.Exists(_sourceFolder))
+ if (!Directory.Exists(_appPath))
{
ShowError("This update utility can only be executed by the main Tango.");
Environment.Exit(0);
@@ -88,6 +88,7 @@ namespace Tango.PPC.Updater
private void Update()
{
EnsureTangoIsDown();
+ RemoveOldDLLFiles();
ReplaceFiles();
StartTango();
Environment.Exit(0);
@@ -114,7 +115,14 @@ namespace Tango.PPC.Updater
foreach (string dirPath in Directory.GetDirectories(_sourceFolder, "*", SearchOption.AllDirectories))
{
- Directory.CreateDirectory(dirPath.Replace(_sourceFolder, _appPath));
+ try
+ {
+ Directory.CreateDirectory(dirPath.Replace(_sourceFolder, _appPath));
+ }
+ catch (Exception ex)
+ {
+ ShowError("Could not create directory " + Path.GetFileName(dirPath) + Environment.NewLine + ex.Message);
+ }
}
foreach (string newPath in Directory.GetFiles(_sourceFolder, "*.*", SearchOption.AllDirectories))
@@ -136,18 +144,26 @@ namespace Tango.PPC.Updater
{
if (!newPath.ToLower().Contains("updater.exe"))
{
- throw ex;
+ ShowError("Could not create file " + Path.GetFileName(newPath) + Environment.NewLine + ex.Message);
}
}
}
+ }
- try
- {
- Directory.Delete(_sourceFolder, true);
- }
- catch (Exception ex)
+ private void RemoveOldDLLFiles()
+ {
+ foreach (string dll in Directory.GetFiles(_appPath, "*.dll"))
{
- Debug.WriteLine(ex.ToString());
+ try
+ {
+ File.Delete(dll);
+ }
+ catch
+ {
+ ShowError($"The file '{Path.GetFileName(dll)}' could not be removed. Please close all instances of Tango and press OK.");
+ RemoveOldDLLFiles();
+ return;
+ }
}
}
@@ -160,11 +176,23 @@ namespace Tango.PPC.Updater
do
{
appProcess = Process.GetProcessesByName(_msProcessName).FirstOrDefault();
+ Process p = new Process();
+ p.StartInfo.CreateNoWindow = true;
+ p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ p.StartInfo.FileName = "wmic";
+ p.StartInfo.Arguments = String.Format("process where name='{0}' delete", _msProcessName);
if (appProcess != null)
{
tries++;
appProcess.Kill();
+
+ try
+ {
+ p.Start();
+ }
+ catch { }
+
Thread.Sleep(1000);
}
diff --git a/Software/Visual_Studio/Tango.Logging/ConsoleWindow.xaml b/Software/Visual_Studio/Tango.Logging/ConsoleWindow.xaml
index e73ccf415..df1f0da25 100644
--- a/Software/Visual_Studio/Tango.Logging/ConsoleWindow.xaml
+++ b/Software/Visual_Studio/Tango.Logging/ConsoleWindow.xaml
@@ -5,7 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Tango.Logging"
mc:Ignorable="d"
- Height="500" Width="800" Background="Black" FontSize="13" Topmost="True" Foreground="Gainsboro" FontFamily="Lucida Console" Title="Console Emulator" RenderOptions.EdgeMode="Aliased">
+ Height="500" Width="800" Background="Black" FontSize="11" Topmost="True" Foreground="Gainsboro" Title="Console Emulator" RenderOptions.EdgeMode="Aliased">
<Grid>
<RichTextBox x:Name="txtLog" Background="Black" BorderThickness="0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Visible"></RichTextBox>
</Grid>
diff --git a/Software/Visual_Studio/Tango.Logging/ConsoleWindow.xaml.cs b/Software/Visual_Studio/Tango.Logging/ConsoleWindow.xaml.cs
index 04e5ab2fa..161c786d3 100644
--- a/Software/Visual_Studio/Tango.Logging/ConsoleWindow.xaml.cs
+++ b/Software/Visual_Studio/Tango.Logging/ConsoleWindow.xaml.cs
@@ -33,7 +33,7 @@ namespace Tango.Logging
{
InitializeComponent();
- txtLog.Document.LineHeight = 15;
+ txtLog.Document.LineHeight = 12;
txtLog.Document.PageWidth = 4000;
_currentBrush = Brushes.Gainsboro;
diff --git a/Software/Visual_Studio/Tango.PMR/Synchronization/CheckForUpdateRequest.cs b/Software/Visual_Studio/Tango.PMR/Synchronization/CheckForUpdateRequest.cs
new file mode 100644
index 000000000..c873c62a5
--- /dev/null
+++ b/Software/Visual_Studio/Tango.PMR/Synchronization/CheckForUpdateRequest.cs
@@ -0,0 +1,188 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: CheckForUpdateRequest.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Tango.PMR.Synchronization {
+
+ /// <summary>Holder for reflection information generated from CheckForUpdateRequest.proto</summary>
+ public static partial class CheckForUpdateRequestReflection {
+
+ #region Descriptor
+ /// <summary>File descriptor for CheckForUpdateRequest.proto</summary>
+ public static pbr::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbr::FileDescriptor descriptor;
+
+ static CheckForUpdateRequestReflection() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "ChtDaGVja0ZvclVwZGF0ZVJlcXVlc3QucHJvdG8SGVRhbmdvLlBNUi5TeW5j",
+ "aHJvbml6YXRpb24iPgoVQ2hlY2tGb3JVcGRhdGVSZXF1ZXN0EhQKDFNlcmlh",
+ "bE51bWJlchgBIAEoCRIPCgdWZXJzaW9uGAIgASgJQiUKI2NvbS50d2luZS50",
+ "YW5nby5wbXIuc3luY2hyb25pemF0aW9uYgZwcm90bzM="));
+ descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+ new pbr::FileDescriptor[] { },
+ new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+ new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.Synchronization.CheckForUpdateRequest), global::Tango.PMR.Synchronization.CheckForUpdateRequest.Parser, new[]{ "SerialNumber", "Version" }, null, null, null)
+ }));
+ }
+ #endregion
+
+ }
+ #region Messages
+ public sealed partial class CheckForUpdateRequest : pb::IMessage<CheckForUpdateRequest> {
+ private static readonly pb::MessageParser<CheckForUpdateRequest> _parser = new pb::MessageParser<CheckForUpdateRequest>(() => new CheckForUpdateRequest());
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pb::MessageParser<CheckForUpdateRequest> Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Tango.PMR.Synchronization.CheckForUpdateRequestReflection.Descriptor.MessageTypes[0]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public CheckForUpdateRequest() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public CheckForUpdateRequest(CheckForUpdateRequest other) : this() {
+ serialNumber_ = other.serialNumber_;
+ version_ = other.version_;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public CheckForUpdateRequest Clone() {
+ return new CheckForUpdateRequest(this);
+ }
+
+ /// <summary>Field number for the "SerialNumber" field.</summary>
+ public const int SerialNumberFieldNumber = 1;
+ private string serialNumber_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string SerialNumber {
+ get { return serialNumber_; }
+ set {
+ serialNumber_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// <summary>Field number for the "Version" field.</summary>
+ public const int VersionFieldNumber = 2;
+ private string version_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string Version {
+ get { return version_; }
+ set {
+ version_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override bool Equals(object other) {
+ return Equals(other as CheckForUpdateRequest);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public bool Equals(CheckForUpdateRequest other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (SerialNumber != other.SerialNumber) return false;
+ if (Version != other.Version) return false;
+ return true;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override int GetHashCode() {
+ int hash = 1;
+ if (SerialNumber.Length != 0) hash ^= SerialNumber.GetHashCode();
+ if (Version.Length != 0) hash ^= Version.GetHashCode();
+ return hash;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (SerialNumber.Length != 0) {
+ output.WriteRawTag(10);
+ output.WriteString(SerialNumber);
+ }
+ if (Version.Length != 0) {
+ output.WriteRawTag(18);
+ output.WriteString(Version);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int CalculateSize() {
+ int size = 0;
+ if (SerialNumber.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(SerialNumber);
+ }
+ if (Version.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Version);
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(CheckForUpdateRequest other) {
+ if (other == null) {
+ return;
+ }
+ if (other.SerialNumber.Length != 0) {
+ SerialNumber = other.SerialNumber;
+ }
+ if (other.Version.Length != 0) {
+ Version = other.Version;
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ SerialNumber = input.ReadString();
+ break;
+ }
+ case 18: {
+ Version = input.ReadString();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/Software/Visual_Studio/Tango.PMR/Synchronization/CheckForUpdateResponse.cs b/Software/Visual_Studio/Tango.PMR/Synchronization/CheckForUpdateResponse.cs
new file mode 100644
index 000000000..736c653e5
--- /dev/null
+++ b/Software/Visual_Studio/Tango.PMR/Synchronization/CheckForUpdateResponse.cs
@@ -0,0 +1,188 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: CheckForUpdateResponse.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Tango.PMR.Synchronization {
+
+ /// <summary>Holder for reflection information generated from CheckForUpdateResponse.proto</summary>
+ public static partial class CheckForUpdateResponseReflection {
+
+ #region Descriptor
+ /// <summary>File descriptor for CheckForUpdateResponse.proto</summary>
+ public static pbr::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbr::FileDescriptor descriptor;
+
+ static CheckForUpdateResponseReflection() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "ChxDaGVja0ZvclVwZGF0ZVJlc3BvbnNlLnByb3RvEhlUYW5nby5QTVIuU3lu",
+ "Y2hyb25pemF0aW9uIkQKFkNoZWNrRm9yVXBkYXRlUmVzcG9uc2USGQoRSXNV",
+ "cGRhdGVBdmFpbGFibGUYASABKAgSDwoHVmVyc2lvbhgCIAEoCUIlCiNjb20u",
+ "dHdpbmUudGFuZ28ucG1yLnN5bmNocm9uaXphdGlvbmIGcHJvdG8z"));
+ descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+ new pbr::FileDescriptor[] { },
+ new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+ new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.Synchronization.CheckForUpdateResponse), global::Tango.PMR.Synchronization.CheckForUpdateResponse.Parser, new[]{ "IsUpdateAvailable", "Version" }, null, null, null)
+ }));
+ }
+ #endregion
+
+ }
+ #region Messages
+ public sealed partial class CheckForUpdateResponse : pb::IMessage<CheckForUpdateResponse> {
+ private static readonly pb::MessageParser<CheckForUpdateResponse> _parser = new pb::MessageParser<CheckForUpdateResponse>(() => new CheckForUpdateResponse());
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pb::MessageParser<CheckForUpdateResponse> Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Tango.PMR.Synchronization.CheckForUpdateResponseReflection.Descriptor.MessageTypes[0]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public CheckForUpdateResponse() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public CheckForUpdateResponse(CheckForUpdateResponse other) : this() {
+ isUpdateAvailable_ = other.isUpdateAvailable_;
+ version_ = other.version_;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public CheckForUpdateResponse Clone() {
+ return new CheckForUpdateResponse(this);
+ }
+
+ /// <summary>Field number for the "IsUpdateAvailable" field.</summary>
+ public const int IsUpdateAvailableFieldNumber = 1;
+ private bool isUpdateAvailable_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public bool IsUpdateAvailable {
+ get { return isUpdateAvailable_; }
+ set {
+ isUpdateAvailable_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Version" field.</summary>
+ public const int VersionFieldNumber = 2;
+ private string version_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string Version {
+ get { return version_; }
+ set {
+ version_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override bool Equals(object other) {
+ return Equals(other as CheckForUpdateResponse);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public bool Equals(CheckForUpdateResponse other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (IsUpdateAvailable != other.IsUpdateAvailable) return false;
+ if (Version != other.Version) return false;
+ return true;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override int GetHashCode() {
+ int hash = 1;
+ if (IsUpdateAvailable != false) hash ^= IsUpdateAvailable.GetHashCode();
+ if (Version.Length != 0) hash ^= Version.GetHashCode();
+ return hash;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (IsUpdateAvailable != false) {
+ output.WriteRawTag(8);
+ output.WriteBool(IsUpdateAvailable);
+ }
+ if (Version.Length != 0) {
+ output.WriteRawTag(18);
+ output.WriteString(Version);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int CalculateSize() {
+ int size = 0;
+ if (IsUpdateAvailable != false) {
+ size += 1 + 1;
+ }
+ if (Version.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Version);
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(CheckForUpdateResponse other) {
+ if (other == null) {
+ return;
+ }
+ if (other.IsUpdateAvailable != false) {
+ IsUpdateAvailable = other.IsUpdateAvailable;
+ }
+ if (other.Version.Length != 0) {
+ Version = other.Version;
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 8: {
+ IsUpdateAvailable = input.ReadBool();
+ break;
+ }
+ case 18: {
+ Version = input.ReadString();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/Software/Visual_Studio/Tango.PMR/Synchronization/DownloadUpdateRequest.cs b/Software/Visual_Studio/Tango.PMR/Synchronization/DownloadUpdateRequest.cs
new file mode 100644
index 000000000..26a0eb8ff
--- /dev/null
+++ b/Software/Visual_Studio/Tango.PMR/Synchronization/DownloadUpdateRequest.cs
@@ -0,0 +1,160 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: DownloadUpdateRequest.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Tango.PMR.Synchronization {
+
+ /// <summary>Holder for reflection information generated from DownloadUpdateRequest.proto</summary>
+ public static partial class DownloadUpdateRequestReflection {
+
+ #region Descriptor
+ /// <summary>File descriptor for DownloadUpdateRequest.proto</summary>
+ public static pbr::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbr::FileDescriptor descriptor;
+
+ static DownloadUpdateRequestReflection() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "ChtEb3dubG9hZFVwZGF0ZVJlcXVlc3QucHJvdG8SGVRhbmdvLlBNUi5TeW5j",
+ "aHJvbml6YXRpb24iLQoVRG93bmxvYWRVcGRhdGVSZXF1ZXN0EhQKDFNlcmlh",
+ "bE51bWJlchgBIAEoCUIlCiNjb20udHdpbmUudGFuZ28ucG1yLnN5bmNocm9u",
+ "aXphdGlvbmIGcHJvdG8z"));
+ descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+ new pbr::FileDescriptor[] { },
+ new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+ new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.Synchronization.DownloadUpdateRequest), global::Tango.PMR.Synchronization.DownloadUpdateRequest.Parser, new[]{ "SerialNumber" }, null, null, null)
+ }));
+ }
+ #endregion
+
+ }
+ #region Messages
+ public sealed partial class DownloadUpdateRequest : pb::IMessage<DownloadUpdateRequest> {
+ private static readonly pb::MessageParser<DownloadUpdateRequest> _parser = new pb::MessageParser<DownloadUpdateRequest>(() => new DownloadUpdateRequest());
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pb::MessageParser<DownloadUpdateRequest> Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Tango.PMR.Synchronization.DownloadUpdateRequestReflection.Descriptor.MessageTypes[0]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public DownloadUpdateRequest() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public DownloadUpdateRequest(DownloadUpdateRequest other) : this() {
+ serialNumber_ = other.serialNumber_;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public DownloadUpdateRequest Clone() {
+ return new DownloadUpdateRequest(this);
+ }
+
+ /// <summary>Field number for the "SerialNumber" field.</summary>
+ public const int SerialNumberFieldNumber = 1;
+ private string serialNumber_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string SerialNumber {
+ get { return serialNumber_; }
+ set {
+ serialNumber_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override bool Equals(object other) {
+ return Equals(other as DownloadUpdateRequest);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public bool Equals(DownloadUpdateRequest other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (SerialNumber != other.SerialNumber) return false;
+ return true;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override int GetHashCode() {
+ int hash = 1;
+ if (SerialNumber.Length != 0) hash ^= SerialNumber.GetHashCode();
+ return hash;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (SerialNumber.Length != 0) {
+ output.WriteRawTag(10);
+ output.WriteString(SerialNumber);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int CalculateSize() {
+ int size = 0;
+ if (SerialNumber.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(SerialNumber);
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(DownloadUpdateRequest other) {
+ if (other == null) {
+ return;
+ }
+ if (other.SerialNumber.Length != 0) {
+ SerialNumber = other.SerialNumber;
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ SerialNumber = input.ReadString();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/Software/Visual_Studio/Tango.PMR/Synchronization/DownloadUpdateResponse.cs b/Software/Visual_Studio/Tango.PMR/Synchronization/DownloadUpdateResponse.cs
new file mode 100644
index 000000000..373f68b5d
--- /dev/null
+++ b/Software/Visual_Studio/Tango.PMR/Synchronization/DownloadUpdateResponse.cs
@@ -0,0 +1,359 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: DownloadUpdateResponse.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Tango.PMR.Synchronization {
+
+ /// <summary>Holder for reflection information generated from DownloadUpdateResponse.proto</summary>
+ public static partial class DownloadUpdateResponseReflection {
+
+ #region Descriptor
+ /// <summary>File descriptor for DownloadUpdateResponse.proto</summary>
+ public static pbr::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbr::FileDescriptor descriptor;
+
+ static DownloadUpdateResponseReflection() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "ChxEb3dubG9hZFVwZGF0ZVJlc3BvbnNlLnByb3RvEhlUYW5nby5QTVIuU3lu",
+ "Y2hyb25pemF0aW9uIrcBChZEb3dubG9hZFVwZGF0ZVJlc3BvbnNlEg8KB1Zl",
+ "cnNpb24YASABKAkSEgoKRnRwQWRkcmVzcxgCIAEoCRITCgtGdHBGaWxlUGF0",
+ "aBgDIAEoCRITCgtGdHBVc2VyTmFtZRgEIAEoCRITCgtGdHBQYXNzd29yZBgF",
+ "IAEoCRIRCglEYkFkZHJlc3MYBiABKAkSEgoKRGJVc2VyTmFtZRgHIAEoCRIS",
+ "CgpEYlBhc3N3b3JkGAggASgJQiUKI2NvbS50d2luZS50YW5nby5wbXIuc3lu",
+ "Y2hyb25pemF0aW9uYgZwcm90bzM="));
+ descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+ new pbr::FileDescriptor[] { },
+ new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+ new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.Synchronization.DownloadUpdateResponse), global::Tango.PMR.Synchronization.DownloadUpdateResponse.Parser, new[]{ "Version", "FtpAddress", "FtpFilePath", "FtpUserName", "FtpPassword", "DbAddress", "DbUserName", "DbPassword" }, null, null, null)
+ }));
+ }
+ #endregion
+
+ }
+ #region Messages
+ public sealed partial class DownloadUpdateResponse : pb::IMessage<DownloadUpdateResponse> {
+ private static readonly pb::MessageParser<DownloadUpdateResponse> _parser = new pb::MessageParser<DownloadUpdateResponse>(() => new DownloadUpdateResponse());
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pb::MessageParser<DownloadUpdateResponse> Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Tango.PMR.Synchronization.DownloadUpdateResponseReflection.Descriptor.MessageTypes[0]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public DownloadUpdateResponse() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public DownloadUpdateResponse(DownloadUpdateResponse other) : this() {
+ version_ = other.version_;
+ ftpAddress_ = other.ftpAddress_;
+ ftpFilePath_ = other.ftpFilePath_;
+ ftpUserName_ = other.ftpUserName_;
+ ftpPassword_ = other.ftpPassword_;
+ dbAddress_ = other.dbAddress_;
+ dbUserName_ = other.dbUserName_;
+ dbPassword_ = other.dbPassword_;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public DownloadUpdateResponse Clone() {
+ return new DownloadUpdateResponse(this);
+ }
+
+ /// <summary>Field number for the "Version" field.</summary>
+ public const int VersionFieldNumber = 1;
+ private string version_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string Version {
+ get { return version_; }
+ set {
+ version_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// <summary>Field number for the "FtpAddress" field.</summary>
+ public const int FtpAddressFieldNumber = 2;
+ private string ftpAddress_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string FtpAddress {
+ get { return ftpAddress_; }
+ set {
+ ftpAddress_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// <summary>Field number for the "FtpFilePath" field.</summary>
+ public const int FtpFilePathFieldNumber = 3;
+ private string ftpFilePath_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string FtpFilePath {
+ get { return ftpFilePath_; }
+ set {
+ ftpFilePath_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// <summary>Field number for the "FtpUserName" field.</summary>
+ public const int FtpUserNameFieldNumber = 4;
+ private string ftpUserName_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string FtpUserName {
+ get { return ftpUserName_; }
+ set {
+ ftpUserName_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// <summary>Field number for the "FtpPassword" field.</summary>
+ public const int FtpPasswordFieldNumber = 5;
+ private string ftpPassword_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string FtpPassword {
+ get { return ftpPassword_; }
+ set {
+ ftpPassword_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// <summary>Field number for the "DbAddress" field.</summary>
+ public const int DbAddressFieldNumber = 6;
+ private string dbAddress_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string DbAddress {
+ get { return dbAddress_; }
+ set {
+ dbAddress_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// <summary>Field number for the "DbUserName" field.</summary>
+ public const int DbUserNameFieldNumber = 7;
+ private string dbUserName_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string DbUserName {
+ get { return dbUserName_; }
+ set {
+ dbUserName_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// <summary>Field number for the "DbPassword" field.</summary>
+ public const int DbPasswordFieldNumber = 8;
+ private string dbPassword_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string DbPassword {
+ get { return dbPassword_; }
+ set {
+ dbPassword_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override bool Equals(object other) {
+ return Equals(other as DownloadUpdateResponse);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public bool Equals(DownloadUpdateResponse other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (Version != other.Version) return false;
+ if (FtpAddress != other.FtpAddress) return false;
+ if (FtpFilePath != other.FtpFilePath) return false;
+ if (FtpUserName != other.FtpUserName) return false;
+ if (FtpPassword != other.FtpPassword) return false;
+ if (DbAddress != other.DbAddress) return false;
+ if (DbUserName != other.DbUserName) return false;
+ if (DbPassword != other.DbPassword) return false;
+ return true;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override int GetHashCode() {
+ int hash = 1;
+ if (Version.Length != 0) hash ^= Version.GetHashCode();
+ if (FtpAddress.Length != 0) hash ^= FtpAddress.GetHashCode();
+ if (FtpFilePath.Length != 0) hash ^= FtpFilePath.GetHashCode();
+ if (FtpUserName.Length != 0) hash ^= FtpUserName.GetHashCode();
+ if (FtpPassword.Length != 0) hash ^= FtpPassword.GetHashCode();
+ if (DbAddress.Length != 0) hash ^= DbAddress.GetHashCode();
+ if (DbUserName.Length != 0) hash ^= DbUserName.GetHashCode();
+ if (DbPassword.Length != 0) hash ^= DbPassword.GetHashCode();
+ return hash;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (Version.Length != 0) {
+ output.WriteRawTag(10);
+ output.WriteString(Version);
+ }
+ if (FtpAddress.Length != 0) {
+ output.WriteRawTag(18);
+ output.WriteString(FtpAddress);
+ }
+ if (FtpFilePath.Length != 0) {
+ output.WriteRawTag(26);
+ output.WriteString(FtpFilePath);
+ }
+ if (FtpUserName.Length != 0) {
+ output.WriteRawTag(34);
+ output.WriteString(FtpUserName);
+ }
+ if (FtpPassword.Length != 0) {
+ output.WriteRawTag(42);
+ output.WriteString(FtpPassword);
+ }
+ if (DbAddress.Length != 0) {
+ output.WriteRawTag(50);
+ output.WriteString(DbAddress);
+ }
+ if (DbUserName.Length != 0) {
+ output.WriteRawTag(58);
+ output.WriteString(DbUserName);
+ }
+ if (DbPassword.Length != 0) {
+ output.WriteRawTag(66);
+ output.WriteString(DbPassword);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int CalculateSize() {
+ int size = 0;
+ if (Version.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Version);
+ }
+ if (FtpAddress.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(FtpAddress);
+ }
+ if (FtpFilePath.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(FtpFilePath);
+ }
+ if (FtpUserName.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(FtpUserName);
+ }
+ if (FtpPassword.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(FtpPassword);
+ }
+ if (DbAddress.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(DbAddress);
+ }
+ if (DbUserName.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(DbUserName);
+ }
+ if (DbPassword.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(DbPassword);
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(DownloadUpdateResponse other) {
+ if (other == null) {
+ return;
+ }
+ if (other.Version.Length != 0) {
+ Version = other.Version;
+ }
+ if (other.FtpAddress.Length != 0) {
+ FtpAddress = other.FtpAddress;
+ }
+ if (other.FtpFilePath.Length != 0) {
+ FtpFilePath = other.FtpFilePath;
+ }
+ if (other.FtpUserName.Length != 0) {
+ FtpUserName = other.FtpUserName;
+ }
+ if (other.FtpPassword.Length != 0) {
+ FtpPassword = other.FtpPassword;
+ }
+ if (other.DbAddress.Length != 0) {
+ DbAddress = other.DbAddress;
+ }
+ if (other.DbUserName.Length != 0) {
+ DbUserName = other.DbUserName;
+ }
+ if (other.DbPassword.Length != 0) {
+ DbPassword = other.DbPassword;
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ Version = input.ReadString();
+ break;
+ }
+ case 18: {
+ FtpAddress = input.ReadString();
+ break;
+ }
+ case 26: {
+ FtpFilePath = input.ReadString();
+ break;
+ }
+ case 34: {
+ FtpUserName = input.ReadString();
+ break;
+ }
+ case 42: {
+ FtpPassword = input.ReadString();
+ break;
+ }
+ case 50: {
+ DbAddress = input.ReadString();
+ break;
+ }
+ case 58: {
+ DbUserName = input.ReadString();
+ break;
+ }
+ case 66: {
+ DbPassword = input.ReadString();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj b/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj
index 4090031e9..d2ea08115 100644
--- a/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj
+++ b/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj
@@ -191,7 +191,14 @@
<Compile Include="Common\MessageContainer.cs" />
<Compile Include="Common\MessageType.cs" />
<Compile Include="Stubs\*.cs" />
- <Compile Include="Synchronization\*.cs" />
+ <Compile Include="Synchronization\MachineSetupRequest.cs" />
+ <Compile Include="Synchronization\MachineSetupResponse.cs" />
+ <Compile Include="Synchronization\SynchronizeDBRequest.cs" />
+ <Compile Include="Synchronization\SynchronizeDBResponse.cs" />
+ <Compile Include="Synchronization\CheckForUpdateRequest.cs" />
+ <Compile Include="Synchronization\CheckForUpdateResponse.cs" />
+ <Compile Include="Synchronization\DownloadUpdateRequest.cs" />
+ <Compile Include="Synchronization\DownloadUpdateResponse.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Utilities\Tango.Protobuf.CLI\Tango.Protobuf.CLI.csproj">
@@ -208,7 +215,7 @@
</PropertyGroup>
<ProjectExtensions>
<VisualStudio>
- <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" />
+ <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" />
</VisualStudio>
</ProjectExtensions>
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs b/Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs
index d21a562fd..d7af7200e 100644
--- a/Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs
+++ b/Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs
@@ -356,8 +356,10 @@ namespace Tango.SharedUI.Controls
private void Navigate(NavigationElement fromElement, NavigationElement toElement)
{
- if (toElement == null) return;
- if (toElement == fromElement) return;
+ if (toElement == null || toElement == fromElement)
+ {
+ _onCompleted?.Invoke();
+ }
if (fromElement != null)
{
@@ -516,7 +518,14 @@ namespace Tango.SharedUI.Controls
if (element != null)
{
- SelectedElement = element;
+ if (SelectedElement == element)
+ {
+ _onCompleted?.Invoke();
+ }
+ else
+ {
+ SelectedElement = element;
+ }
}
return element;
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/SynchronizationController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/SynchronizationController.cs
index 8054aae8c..e4e01e7d1 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/SynchronizationController.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/SynchronizationController.cs
@@ -125,6 +125,102 @@ namespace Tango.MachineService.Controllers
return response;
}
+ [HttpPost]
+ public DownloadUpdateResponse MachineUpdate(DownloadUpdateRequest request)
+ {
+ DownloadUpdateResponse response = new DownloadUpdateResponse();
+
+ try
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault(GetLocalServerAddress()))
+ {
+ db.Configuration.LazyLoadingEnabled = false;
+ String serial_number = request.SerialNumber;
+
+ var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == serial_number);
+
+ if (machine == null)
+ {
+ OnError(HttpStatusCode.NotFound, "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;
+
+ response.FtpAddress = GetFtpAddress();
+ response.FtpFilePath = latest_machine_version.FtpFilePath;
+ response.FtpUserName = GetFtpUserName();
+ response.FtpPassword = GetFtpPassword();
+
+ DbCredentials credentials = new DbCredentials();
+
+ using (DbManager manager = DbManager.FromAddressAndName(GetDbAddress(), "Tango"))
+ {
+ credentials = manager.CreateRandomLoginAndUser("Tango");
+
+ Task.Delay(TimeSpan.FromMinutes(10)).ContinueWith((x) =>
+ {
+ using (DbManager m = DbManager.FromAddressAndName(GetDbAddress(), "Tango"))
+ {
+ m.DeleteLoginAndUser(credentials.UserName, "Tango");
+ }
+ });
+ }
+
+ response.DbAddress = GetDbAddress();
+ response.DbUserName = credentials.UserName;
+ response.DbPassword = credentials.Password;
+ }
+ }
+ catch (Exception ex)
+ {
+ OnError(HttpStatusCode.InternalServerError, ex.Message);
+ }
+
+ return response;
+ }
+
+ [HttpPost]
+ public CheckForUpdateResponse CheckForUpdate(CheckForUpdateRequest request)
+ {
+ CheckForUpdateResponse response = new CheckForUpdateResponse();
+
+ try
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault(GetLocalServerAddress()))
+ {
+ db.Configuration.LazyLoadingEnabled = false;
+
+ var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == request.SerialNumber);
+
+ if (machine == null)
+ {
+ OnError(HttpStatusCode.NotFound, "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();
+
+ if (Version.Parse(latest_machine_version.Version) > Version.Parse(request.Version))
+ {
+ response.IsUpdateAvailable = true;
+ }
+
+ response.Version = latest_machine_version.Version;
+ }
+ }
+ catch (Exception ex)
+ {
+ OnError(HttpStatusCode.InternalServerError, ex.Message);
+ }
+
+ return response;
+ }
+
#region Helpers
private void OnError(HttpStatusCode code, String message)