From 4e216a0ca8ad3608b845fa445b73034e1a67b8af Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Wed, 19 Aug 2020 01:45:02 +0300 Subject: DB: Changed TechMonitors HeadZone5_6HeaterCurrent => HeadZone56HeaterCurrent Working on insights and insights annotations. Added insights events. Added insights settings to PPC advanced settings. Added compression support for transport adapters. Implemented compression support on TCP/SignalR/WebRTC. Added Compression flag to ExternalBridge discovery packet. Added compression setting to PPC advanced settings. Refactored transport layer to use Bson instead of Json for Generic Messages. Added all SciChart referenced assemblies. Registered EF Extensions license for FSE. Added support for FSE PushTask notification cancel button. --- .../Tango.PPC.MachineSettings/Views/MainView.xaml | 27 +++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings') diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml index 4f7385513..d436c58b7 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml @@ -296,12 +296,17 @@ + + External Bridge Transport Compression + + + Enable External Bridge SignalR - + External Bridge SignalR Hub @@ -328,6 +333,26 @@ + + Enable Insights + + + + + Insights Sampling Interval (sec) + + + + + Insights Storage Cleanup Interval (min) + + + + + Insights Max Storage Duration (days) + + + -- cgit v1.3.1 From 7bd70fcb311c808b65b62e774755dcbd6b0d63cd Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Fri, 21 Aug 2020 12:58:15 +0300 Subject: Insights anomalies. --- .../Dialogs/AnomaliesDialogView.xaml | 54 ++ .../Dialogs/AnomaliesDialogView.xaml.cs | 28 ++ .../Dialogs/AnomaliesDialogViewVM.cs | 66 +++ .../Tango.FSE.Insights/Images/detection.png | Bin 0 -> 5717 bytes .../Tango.FSE.Insights/Images/insight_big.png | Bin 0 -> 7682 bytes .../FSE/Modules/Tango.FSE.Insights/Images/time.png | Bin 9091 -> 4974 bytes .../ML/AnomaliesDetectionProgress.cs | 30 ++ .../Tango.FSE.Insights/ML/AnomaliesDetector.cs | 63 +++ .../Modules/Tango.FSE.Insights/ML/AnomalyType.cs | 13 + .../Tango.FSE.Insights/ML/DetectedAnnomaly.cs | 21 + .../ML/MonitorSeriesPrediction.cs | 15 + .../Modules/Tango.FSE.Insights/ML/MonitorValue.cs | 17 + .../Tango.FSE.Insights/SciChart/InsightsChart.cs | 101 +++- .../Tango.FSE.Insights/Tango.FSE.Insights.csproj | 85 +++- .../Modules/Tango.FSE.Insights/Themes/Generic.xaml | 7 + .../ViewModels/InsightsViewVM.cs | 262 +++++++++- .../Tango.FSE.Insights/Views/InsightsView.xaml | 545 +++++++++++++-------- .../FSE/Modules/Tango.FSE.Insights/app.config | 44 +- .../FSE/Modules/Tango.FSE.Insights/packages.config | 16 +- .../Tango.FSE.Common/Insights/IInsightsProvider.cs | 1 + Software/Visual_Studio/FSE/Tango.FSE.UI/App.config | 10 +- .../Insights/DefaultInsightsProvider.cs | 42 +- .../FSE/Tango.FSE.UI/Tango.FSE.UI.csproj | 4 +- .../Visual_Studio/FSE/Tango.FSE.UI/packages.config | 2 +- .../Tango.PPC.MachineSettings/Views/MainView.xaml | 4 +- .../EventLogging/DefaultEventLogger.cs | 12 +- .../Insights/DefaultInsightsService.cs | 38 ++ .../Insights/InsightsDownloadCompletedRequest.cs | 13 + .../Insights/InsightsDownloadCompletedResponse.cs | 12 + .../Insights/InsightsMinDateRequest.cs | 12 + .../Insights/InsightsMinDateResponse.cs | 13 + .../PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj | 4 + .../Tango.Core/ExtensionMethods/ListExtensions.cs | 26 + .../Visual_Studio/Tango.Core/Tango.Core.csproj | 3 +- .../Tango.Insights/InsightsManager.cs | 27 +- 35 files changed, 1341 insertions(+), 249 deletions(-) create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Dialogs/AnomaliesDialogView.xaml create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Dialogs/AnomaliesDialogView.xaml.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Dialogs/AnomaliesDialogViewVM.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/detection.png create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/insight_big.png create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/AnomaliesDetectionProgress.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/AnomaliesDetector.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/AnomalyType.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/DetectedAnnomaly.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/MonitorSeriesPrediction.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/MonitorValue.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsDownloadCompletedRequest.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsDownloadCompletedResponse.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsMinDateRequest.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsMinDateResponse.cs create mode 100644 Software/Visual_Studio/Tango.Core/ExtensionMethods/ListExtensions.cs (limited to 'Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings') diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Dialogs/AnomaliesDialogView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Dialogs/AnomaliesDialogView.xaml new file mode 100644 index 000000000..375f0be0d --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Dialogs/AnomaliesDialogView.xaml @@ -0,0 +1,54 @@ + + + + + + + Anomalies Detection + + + + Anomalies detection can help you diagnose unusual events and behaviors. + + Please select monitors for the analysis and press 'ANALYZE'. + + Once the analysis completes, special chart annotations will be overlayed on the selected monitors charts. + + + + + + + + + + Please specify maximum 8 monitors for analysis + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Dialogs/AnomaliesDialogView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Dialogs/AnomaliesDialogView.xaml.cs new file mode 100644 index 000000000..b8a819b7b --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Dialogs/AnomaliesDialogView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.FSE.Insights.Dialogs +{ + /// + /// Interaction logic for AnomaliesDialogView.xaml + /// + public partial class AnomaliesDialogView : UserControl + { + public AnomaliesDialogView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Dialogs/AnomaliesDialogViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Dialogs/AnomaliesDialogViewVM.cs new file mode 100644 index 000000000..42c71327b --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Dialogs/AnomaliesDialogViewVM.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using Tango.FSE.Common; +using Tango.FSE.Insights.SciChart; +using Tango.SharedUI.Components; + +namespace Tango.FSE.Insights.Dialogs +{ + public class AnomaliesDialogViewVM : FSEDialogViewVM + { + private const int MAX_SELECTION = 8; + private ICollectionView _view; + + public SelectedObjectCollection SelectedCharts { get; set; } + + private String _filter; + public String Filter + { + get { return _filter; } + set { _filter = value; RaisePropertyChangedAuto(); OnFilterChanged(); } + } + + public bool MaximumSelectionReached + { + get { return SelectedCharts.SynchedSource.Count > MAX_SELECTION; } + } + + public AnomaliesDialogViewVM(List availableCharts, List selectedCharts) + { + OKText = "ANALYZE"; + SelectedCharts = new SelectedObjectCollection(availableCharts.OrderByDescending(x => selectedCharts.Contains(x)).ToObservableCollection(), selectedCharts.ToObservableCollection()); + SelectedCharts.SelectionChanged += SelectedCharts_SelectionChanged; + + _view = CollectionViewSource.GetDefaultView(SelectedCharts); + _view.Filter = FilterCharts; + } + + private bool FilterCharts(object obj) + { + if (String.IsNullOrWhiteSpace(Filter)) return true; + return (obj as SelectedObject).Data.Description.ToLower().Contains(Filter.ToLower()); + } + + private void SelectedCharts_SelectionChanged(object sender, EventArgs e) + { + RaisePropertyChanged(nameof(MaximumSelectionReached)); + InvalidateRelayCommands(); + } + + protected override bool CanOK() + { + return base.CanOK() && SelectedCharts.SynchedSource.Count > 0 && !MaximumSelectionReached; + } + + private void OnFilterChanged() + { + _view?.Refresh(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/detection.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/detection.png new file mode 100644 index 000000000..a29355327 Binary files /dev/null and b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/detection.png differ diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/insight_big.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/insight_big.png new file mode 100644 index 000000000..e5cc9e2dc Binary files /dev/null and b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/insight_big.png differ diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/time.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/time.png index 1eb9b077f..542bd09db 100644 Binary files a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/time.png and b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/time.png differ diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/AnomaliesDetectionProgress.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/AnomaliesDetectionProgress.cs new file mode 100644 index 000000000..6331e7de0 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/AnomaliesDetectionProgress.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.FSE.Insights.SciChart; + +namespace Tango.FSE.Insights.ML +{ + public class AnomaliesDetectionProgress : ExtendedObject + { + public InsightsChart Chart { get; set; } + public int FramesCount { get; set; } + private int _currentFrame; + + public int CurrentFrame + { + get { return _currentFrame; } + set + { + if (value > _currentFrame + 9 || value == FramesCount) + { + _currentFrame = value; + RaisePropertyChanged(nameof(CurrentFrame)); + } + } + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/AnomaliesDetector.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/AnomaliesDetector.cs new file mode 100644 index 000000000..4a81e9eb5 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/AnomaliesDetector.cs @@ -0,0 +1,63 @@ +using Microsoft.ML; +using Microsoft.ML.Transforms.TimeSeries; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Insights.ML +{ + public class AnomaliesDetector + { + private IDataView _view; + private MLContext _mlContext; + private List _values; + + private AnomaliesDetector() + { + _mlContext = new MLContext(); + } + + public static Task FromMonitor(List monitorValues) + { + return Task.Factory.StartNew(() => + { + AnomaliesDetector engine = new AnomaliesDetector(); + engine._values = monitorValues; + engine._view = engine._mlContext.Data.LoadFromEnumerable(monitorValues); + return engine; + }); + } + + public void DetectSpikes() + { + var iidSpikeEstimator = _mlContext.Transforms.DetectIidSpike(outputColumnName: nameof(MonitorSeriesPrediction.Prediction), inputColumnName: nameof(MonitorValue.Value), confidence: 95, pvalueHistoryLength: _values.Count / 4, side: AnomalySide.TwoSided); + + ITransformer iidSpikeTransform = iidSpikeEstimator.Fit(CreateEmptyDataView()); + + IDataView transformedData = iidSpikeTransform.Transform(_view); + + var predictions = _mlContext.Data.CreateEnumerable(transformedData, reuseRowObject: false); + + foreach (var p in predictions) + { + var results = $"{p.Prediction[0]}\t{p.Prediction[1]:f2}\t{p.Prediction[2]:F2}"; + + if (p.Prediction[0] == 1) + { + results += " <-- Spike detected"; + } + + Debug.WriteLine(results); + } + } + + private IDataView CreateEmptyDataView() + { + IEnumerable enumerableData = new List(); + return _mlContext.Data.LoadFromEnumerable(enumerableData); + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/AnomalyType.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/AnomalyType.cs new file mode 100644 index 000000000..7f24de856 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/AnomalyType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Insights.ML +{ + public enum AnomalyType + { + Spike, + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/DetectedAnnomaly.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/DetectedAnnomaly.cs new file mode 100644 index 000000000..f031179b7 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/DetectedAnnomaly.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Insights.ML +{ + public class DetectedAnnomaly + { + public AnomalyType Type { get; set; } + public DateTime Time { get; set; } + public double Value { get; set; } + public double Score { get; set; } + + public override string ToString() + { + return $"{Time} => {Type} => {Value}"; + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/MonitorSeriesPrediction.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/MonitorSeriesPrediction.cs new file mode 100644 index 000000000..5c1a1a672 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/MonitorSeriesPrediction.cs @@ -0,0 +1,15 @@ +using Microsoft.ML.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Insights.ML +{ + public class MonitorSeriesPrediction + { + [VectorType(3)] + public double[] Prediction { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/MonitorValue.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/MonitorValue.cs new file mode 100644 index 000000000..c9d6fd9ef --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ML/MonitorValue.cs @@ -0,0 +1,17 @@ +using Microsoft.ML.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Insights.ML +{ + public class MonitorValue + { + public DateTime Time { get; set; } + + [LoadColumn(0)] + public float Value { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsChart.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsChart.cs index c51015e66..be0bff2dc 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsChart.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/SciChart/InsightsChart.cs @@ -1,4 +1,6 @@ -using SciChart.Charting.Model.ChartSeries; +using Microsoft.ML; +using Microsoft.ML.Transforms.TimeSeries; +using SciChart.Charting.Model.ChartSeries; using SciChart.Charting.Model.DataSeries; using SciChart.Charting.Visuals.Annotations; using SciChart.Charting.Visuals.RenderableSeries; @@ -9,8 +11,11 @@ using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; +using System.Windows; using System.Windows.Media; +using Tango.BL.Enumerations; using Tango.Core; +using Tango.FSE.Insights.ML; namespace Tango.FSE.Insights.SciChart { @@ -21,10 +26,13 @@ namespace Tango.FSE.Insights.SciChart private ObservableCollection ChartsCollection { get; set; } public String Name { get; set; } public String Description { get; set; } + public TechMonitors TechMonitor { get; set; } public PropertyInfo InsightsMonitorsProperty { get; set; } public IRenderableSeriesViewModel RenderableSeries { get; set; } public XyDataSeries DataSeries { get; set; } + public List MonitorValues { get; set; } public AnnotationCollection Annotations { get; set; } + public List Anomalies { get; set; } private bool _isVisible; public bool IsVisible @@ -51,6 +59,8 @@ namespace Tango.FSE.Insights.SciChart public InsightsChart(ObservableCollection chartsCollection) { + Anomalies = new List(); + MonitorValues = new List(); ChartsCollection = chartsCollection; ChartsCollection.CollectionChanged += ChartsCollection_CollectionChanged; RenderableSeries = new LineRenderableSeriesViewModel() { DrawNaNAs = LineDrawMode.Gaps }; @@ -64,5 +74,94 @@ namespace Tango.FSE.Insights.SciChart { RaisePropertyChanged(nameof(IsLast)); } + + public List DetectAnnomalies(Action progress = null) + { + List annomalies = new List(); + + if (MonitorValues.Count > 0 && MonitorValues.Any(x => x.Value != 0)) + { + var chunks = MonitorValues.ChunkBy(1000); + + double lastValue = 0; + int totalIndex = 0; + + foreach (var chunk in chunks) + { + MLContext mlContext = new MLContext(); + IDataView view = mlContext.Data.LoadFromEnumerable(chunk); + + var iidSpikeEstimator = mlContext.Transforms.DetectIidSpike(outputColumnName: nameof(MonitorSeriesPrediction.Prediction), inputColumnName: nameof(MonitorValue.Value), confidence: 95, pvalueHistoryLength: chunk.Count / 4, side: AnomalySide.Positive); + + ITransformer iidSpikeTransform = iidSpikeEstimator.Fit(CreateEmptyDataView(mlContext)); + + IDataView transformedData = iidSpikeTransform.Transform(view); + + var predictions = mlContext.Data.CreateEnumerable(transformedData, reuseRowObject: false); + + int index = 0; + + foreach (var p in predictions) + { + if (p.Prediction[2] < (1 - 0.95)) + { + p.Prediction[0] = 1; + } + + if (p.Prediction[0] == 1) + { + var monitorValue = chunk[index]; + + if (lastValue != monitorValue.Value) + { + annomalies.Add(new DetectedAnnomaly() + { + Type = AnomalyType.Spike, + Time = monitorValue.Time, + Value = monitorValue.Value, + Score = p.Prediction[1], + }); + + lastValue = monitorValue.Value; + } + } + + index++; + totalIndex++; + + progress?.Invoke(totalIndex); + } + } + + annomalies = annomalies.OrderByDescending(x => x.Score).Take(10).OrderBy(x => x.Time).ToList(); + } + + progress?.Invoke(MonitorValues.Count); + + Anomalies = annomalies.ToList(); + + return annomalies; + } + + private IDataView CreateEmptyDataView(MLContext context) + { + IEnumerable enumerableData = new List(); + return context.Data.LoadFromEnumerable(enumerableData); + } + + public void DrawAnomalies() + { + foreach (var anomaly in Anomalies) + { + CustomAnnotation annotation = new CustomAnnotation(); + annotation.CoordinateMode = AnnotationCoordinateMode.Absolute; + annotation.X1 = anomaly.Time.ToLocalTime(); + annotation.Y1 = anomaly.Value; + annotation.Content = anomaly; + annotation.ContentTemplate = Application.Current.Resources["InsightAnomalyTemplate"] as DataTemplate; + + Annotations.Add(annotation); + } + } } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Tango.FSE.Insights.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Tango.FSE.Insights.csproj index 65521c65d..ea6616985 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Tango.FSE.Insights.csproj +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Tango.FSE.Insights.csproj @@ -1,5 +1,8 @@  + + + Debug @@ -55,8 +58,36 @@ ..\..\..\packages\MaterialDesignThemes.3.0.1\lib\net45\MaterialDesignThemes.Wpf.dll - - ..\..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + + ..\..\..\packages\Microsoft.ML.1.5.1\lib\netstandard2.0\Microsoft.ML.Core.dll + + + ..\..\..\packages\Microsoft.ML.CpuMath.1.5.1\lib\netstandard2.0\Microsoft.ML.CpuMath.dll + + + ..\..\..\packages\Microsoft.ML.1.5.1\lib\netstandard2.0\Microsoft.ML.Data.dll + + + ..\..\..\packages\Microsoft.ML.DataView.1.5.1\lib\netstandard2.0\Microsoft.ML.DataView.dll + + + ..\..\..\packages\Microsoft.ML.1.5.1\lib\netstandard2.0\Microsoft.ML.KMeansClustering.dll + + + ..\..\..\packages\Microsoft.ML.1.5.1\lib\netstandard2.0\Microsoft.ML.PCA.dll + + + ..\..\..\packages\Microsoft.ML.1.5.1\lib\netstandard2.0\Microsoft.ML.StandardTrainers.dll + + + ..\..\..\packages\Microsoft.ML.TimeSeries.1.5.1\lib\netstandard2.0\Microsoft.ML.TimeSeries.dll + + + ..\..\..\packages\Microsoft.ML.1.5.1\lib\netstandard2.0\Microsoft.ML.Transforms.dll + + + ..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + False False @@ -87,8 +118,33 @@ ..\..\..\Referenced Assemblies\SciChart\SciChart.Drawing.DirectX.dll + + ..\..\..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + ..\..\..\packages\System.CodeDom.4.7.0\lib\net461\System.CodeDom.dll + + + ..\..\..\packages\System.Collections.Immutable.1.7.1\lib\net461\System.Collections.Immutable.dll + + + ..\..\..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + + + ..\..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\..\..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + ..\..\..\packages\System.Threading.Channels.4.7.1\lib\net461\System.Threading.Channels.dll + + + ..\..\..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + ..\..\..\packages\ControlzEx.3.0.2.4\lib\net45\System.Windows.Interactivity.dll @@ -107,6 +163,16 @@ + + AnomaliesDialogView.xaml + + + + + + + + @@ -202,6 +268,10 @@ MSBuild:Compile Designer + + Designer + MSBuild:Compile + MSBuild:Compile Designer @@ -236,6 +306,12 @@ + + + + + + @@ -243,5 +319,10 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Themes/Generic.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Themes/Generic.xaml index f4cd75c76..cf9c18b68 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Themes/Generic.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Themes/Generic.xaml @@ -4,6 +4,7 @@ xmlns:entities="clr-namespace:Tango.BL.Entities;assembly=Tango.BL" xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:commonInsights="clr-namespace:Tango.FSE.Common.Insights;assembly=Tango.FSE.Common" + xmlns:ML="clr-namespace:Tango.FSE.Insights.ML" xmlns:views="clr-namespace:Tango.FSE.Insights.Views" xmlns:local="clr-namespace:Tango.FSE.Diagnostics.Themes"> @@ -129,4 +130,10 @@ + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ViewModels/InsightsViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ViewModels/InsightsViewVM.cs index 0486955e0..b36ef163a 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ViewModels/InsightsViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ViewModels/InsightsViewVM.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; +using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; @@ -21,6 +22,8 @@ using Tango.Core.Commands; using Tango.FSE.Common; using Tango.FSE.Common.Insights; using Tango.FSE.Insights.Contracts; +using Tango.FSE.Insights.Dialogs; +using Tango.FSE.Insights.ML; using Tango.FSE.Insights.Navigation; using Tango.FSE.Insights.SciChart; using Tango.Logging; @@ -32,15 +35,37 @@ namespace Tango.FSE.Insights.ViewModels { private bool _chartsLoaded; private ICollectionView _monitorsView; + private List _lastSelectedForDetection; + private List _defaultChartForAnomalies = new List() + { + TechMonitors.IncomingVoltage, + TechMonitors.ChillerTemperature, + TechMonitors.OverallTemperature, + TechMonitors.GasSensor, + TechMonitors.BlowerVoltage, + TechMonitors.HeadZone1Temperature + }; #region Properties public RelayCommand GetInsightsCommand { get; set; } - public ObservableCollection Charts { get; set; } + private ObservableCollection _charts; + public ObservableCollection Charts + { + get { return _charts; } + set { _charts = value; RaisePropertyChangedAuto(); } + } public ObservableCollection VisibleCharts { get; set; } + private List _anomaliesDetectionProgresses; + public List AnomaliesDetectionProgresses + { + get { return _anomaliesDetectionProgresses; } + set { _anomaliesDetectionProgresses = value; RaisePropertyChangedAuto(); } + } + private DateTime _minDate; public DateTime MinDate { @@ -108,7 +133,7 @@ namespace Tango.FSE.Insights.ViewModels public InsightsPackage InsightsPackage { get { return _insightsPackage; } - set { _insightsPackage = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(InsightsPackageAvailable)); } + set { _insightsPackage = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(InsightsPackageAvailable)); InvalidateRelayCommands(); } } public bool InsightsPackageAvailable @@ -123,6 +148,13 @@ namespace Tango.FSE.Insights.ViewModels set { _displayAnnotations = value; RaisePropertyChangedAuto(); } } + private bool _displayAnomalies; + public bool DisplayAnomalies + { + get { return _displayAnomalies; } + set { _displayAnomalies = value; RaisePropertyChangedAuto(); } + } + private bool _isSearchBarOpened; public bool IsSearchBarOpened { @@ -130,6 +162,21 @@ namespace Tango.FSE.Insights.ViewModels set { _isSearchBarOpened = value; RaisePropertyChangedAuto(); } } + private bool _isSettingsBarOpened; + public bool IsSettingsBarOpened + { + get { return _isSettingsBarOpened; } + set { _isSettingsBarOpened = value; RaisePropertyChangedAuto(); OnIsSettingsBarOpenedChanged(); } + } + + private bool _isDetecting; + public bool IsDetecting + { + get { return _isDetecting; } + set { _isDetecting = value; RaisePropertyChangedAuto(); } + } + + public AnnotationCollection Annotations { get; set; } #endregion @@ -140,19 +187,27 @@ namespace Tango.FSE.Insights.ViewModels public RelayCommand PeekFirmwareLogsCommand { get; set; } + public RelayCommand AnalyzeCommand { get; set; } + #endregion #region Constructors public InsightsViewVM() { + MinDate = DateTime.Now.AddDays(-30); + MaxDate = DateTime.Now; + IsSearchBarOpened = true; + DisplayAnnotations = true; + DisplayAnomalies = true; Charts = new ObservableCollection(); VisibleCharts = new ObservableCollection(); Annotations = new AnnotationCollection(); GetInsightsCommand = new RelayCommand(GetInsights, () => IsFree); PeekApplicationLogsCommand = new RelayCommand(PeekAnnotationApplicationLogs); PeekFirmwareLogsCommand = new RelayCommand(PeekAnnotationFirmwareLogs); + AnalyzeCommand = new RelayCommand(Analyze, () => InsightsPackage != null); } #endregion @@ -166,6 +221,8 @@ namespace Tango.FSE.Insights.ViewModels StartTime = new DateTime(1, 1, 1, 0, 0, 0); EndDate = null; EndTime = null; + + MachineProvider.MachineConnected += MachineProvider_MachineConnected; } public async override void OnApplicationReady() @@ -176,13 +233,14 @@ namespace Tango.FSE.Insights.ViewModels { try { - var monitors = (await Services.TechComponentsService.Monitors.FindAll()).OrderBy(x => x.Description).ToList(); + var monitors = (await Services.TechComponentsService.Monitors.FindAll()).OrderByAlphaNumeric(x => x.Description).ToList(); foreach (var monitor in monitors.Where(x => !x.MultiChannel).ToList()) { InsightsChart chart = new InsightsChart(VisibleCharts); chart.Name = monitor.Name; chart.Description = monitor.Description; + chart.TechMonitor = (TechMonitors)monitor.Code; chart.InsightsMonitorsProperty = typeof(InsightsMonitors).GetProperty(((TechMonitors)monitor.Code).ToString(), BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); chart.IsVisibleChanged += Chart_IsVisibleChanged; chart.DataSeries.Append(GetDemoDates(), GetDemoValues()); @@ -195,25 +253,14 @@ namespace Tango.FSE.Insights.ViewModels LogManager.Log($"Error loading insights chart '{chart.Name}'. Could not find property on InsightsMonitors.", LogCategory.Error); } - _monitorsView = CollectionViewSource.GetDefaultView(Charts); - _monitorsView.Filter = (x) => - { - if (!MonitorsFilter.IsNotNullOrEmpty()) return true; - - InsightsChart chart = x as InsightsChart; - if (chart != null) - { - return chart.Description.ToLower().Contains(MonitorsFilter.ToLower()); - } - - return false; - }; + InitMonitorsView(); _chartsLoaded = true; } catch (Exception ex) { - //TODO: Report Insights module error with BugReporting Snackbar... + LogManager.Log(ex, "Error initializing insights module."); + NotificationProvider.PushErrorReportingSnackbar(ex, "Insights Module Error", "Error initializing insights module."); } } } @@ -225,7 +272,6 @@ namespace Tango.FSE.Insights.ViewModels public override void OnNavigatedTo() { base.OnNavigatedTo(); - MinDate = DateTime.Now.AddDays(-30); MaxDate = DateTime.Now; } @@ -298,7 +344,7 @@ namespace Tango.FSE.Insights.ViewModels } catch (Exception ex) { - throw; + LogManager.Log(ex, "Error aborting insights request."); } })) { @@ -333,6 +379,7 @@ namespace Tango.FSE.Insights.ViewModels IsSearchBarOpened = true; LogManager.Log(ex, "Error getting insights."); await NotificationProvider.ShowError($"Error occurred while trying to get insights.\n{ex.FlattenMessage()}"); + NotificationProvider.PushErrorReportingSnackbar(ex, "Insights Module Error", "Error occurred while trying to retrieve the remote machine insights."); } finally { @@ -359,9 +406,20 @@ namespace Tango.FSE.Insights.ViewModels dates.Add(frame.Frame.Time.ToLocalTime()); + if (value != null) { - values.Add((double)value); + double v = (double)value; + values.Add(v); + + if (!double.IsNaN(v)) + { + chart.MonitorValues.Add(new MonitorValue() + { + Time = frame.Frame.Time, + Value = (float)v + }); + } } else { @@ -376,6 +434,8 @@ namespace Tango.FSE.Insights.ViewModels InvokeUI(() => { Annotations.Clear(); + Charts.ToList().ForEach(x => x.Anomalies.Clear()); + Charts.ToList().ForEach(x => x.Annotations.Clear()); //Load annotations bool disconnected = false; @@ -416,13 +476,13 @@ namespace Tango.FSE.Insights.ViewModels { VerticalLineAnnotation line = new VerticalLineAnnotation(); line.StrokeThickness = 2; - line.Stroke = connected ? Brushes.Green : Brushes.Red; + line.Stroke = connected ? Brushes.Green : Brushes.DarkGray; line.X1 = date; line.X2 = date; line.ShowLabel = false; line.AnnotationLabels.Add(new AnnotationLabel() { - LabelPlacement = LabelPlacement.TopRight, + LabelPlacement = connected ? LabelPlacement.TopRight : LabelPlacement.BottomLeft, Text = connected ? "machine connected" : "machine disconnected" }); Annotations.Add(line); @@ -487,6 +547,33 @@ namespace Tango.FSE.Insights.ViewModels #region Event Handlers + private async void MachineProvider_MachineConnected(object sender, Common.Connection.MachineConnectedEventArgs e) + { + try + { + var date = await InsightsProvider.GetInsightsMinDate(); + + if (date != null) + { + var remoteMinDate = date.Value.ToLocalTime(); + + if (remoteMinDate > StartDate) + { + StartDate = remoteMinDate; + } + + if (remoteMinDate > MinDate) + { + MinDate = remoteMinDate; + } + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error retrieving minimum insights date from the remote machine."); + } + } + private void Chart_IsVisibleChanged(object sender, EventArgs e) { InsightsChart chart = sender as InsightsChart; @@ -503,6 +590,109 @@ namespace Tango.FSE.Insights.ViewModels #endregion + #region Analysis + + private async void Analyze() + { + var defaultCharts = Charts.Where(x => _defaultChartForAnomalies.Exists(y => y == x.TechMonitor)).ToList(); + + if (_lastSelectedForDetection != null) + { + defaultCharts = _lastSelectedForDetection.ToList(); + } + + var vm = await NotificationProvider.ShowDialog(new AnomaliesDialogViewVM(Charts.ToList(), defaultCharts)); + + if (vm.DialogResult && vm.SelectedCharts.SynchedSource.Count > 0) + { + var snackbar = NotificationProvider.PushProgressSnackbar("Anomalies Detection", "Detecting insights anomalies..."); + + try + { + IsDetecting = true; + IsSettingsBarOpened = false; + + var chartsToAnalyze = vm.SelectedCharts.SynchedSource.ToList(); + _lastSelectedForDetection = chartsToAnalyze.ToList(); + + AnomaliesDetectionProgresses = chartsToAnalyze.Select(x => new AnomaliesDetectionProgress() + { + Chart = x, + FramesCount = x.MonitorValues.Count + }).ToList(); + + int counter = 0; + + await Task.Factory.StartNew(() => + { + Stopwatch watch = new Stopwatch(); + watch.Start(); + + double totalCounter = 0; + double totalFrames = chartsToAnalyze.Count * InsightsPackage.Frames.Count; + + Parallel.ForEach(AnomaliesDetectionProgresses, (progress) => + { + counter++; + + Debug.WriteLine($"Analyzing chart '{progress.Chart.Description}'..."); + + progress.Chart.DetectAnnomalies((index) => + { + progress.CurrentFrame = index; + totalCounter++; + //snackbar.Message = $"Detecting insights anomalies ({(int)(totalCounter / totalFrames * 100d)}%)..."; + }); + + foreach (var a in progress.Chart.Anomalies) + { + Debug.WriteLine($"{progress.Chart.Name} => {a.ToString()}"); + } + }); + + watch.Stop(); + + Debug.WriteLine($"Spike detection completed in {(int)watch.Elapsed.TotalMinutes} minutes."); + }); + + Charts.ToList().ForEach(x => x.Annotations.Clear()); + + foreach (var chart in chartsToAnalyze) + { + chart.DrawAnomalies(); + } + + VisibleCharts.ToList().ForEach(x => x.IsVisible = false); + chartsToAnalyze.ForEach(x => x.IsVisible = true); + + IsDetecting = false; + + snackbar.ProgressCompleted("Insights anomalies detection completed.\nTap to view the results.", IsVisible ? TimeSpan.FromSeconds(1) : default(TimeSpan?), () => + { + if (!IsVisible) + { + //Navigate to this view... + } + }); + + View.ZoomExtents(); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error performing anomaly detection on insights."); + snackbar.Close(); + NotificationProvider.PushErrorReportingSnackbar(ex, "Insights Module Error", "Error occurred while trying to perform insights anomalies detection."); + } + finally + { + IsDetecting = false; + IsSearchBarOpened = false; + } + } + } + + #endregion + #region Private Methods private void OnMonitorsFilterChanged() @@ -510,6 +700,32 @@ namespace Tango.FSE.Insights.ViewModels _monitorsView?.Refresh(); } + private void OnIsSettingsBarOpenedChanged() + { + if (!IsSettingsBarOpened) + { + Charts = Charts.OrderByAlphaNumeric(x => x.Description).OrderByDescending(x => x.IsVisible).ToObservableCollection(); + InitMonitorsView(); + } + } + + private void InitMonitorsView() + { + _monitorsView = CollectionViewSource.GetDefaultView(Charts); + _monitorsView.Filter = (x) => + { + if (!MonitorsFilter.IsNotNullOrEmpty()) return true; + + InsightsChart chart = x as InsightsChart; + if (chart != null) + { + return chart.Description.ToLower().Contains(MonitorsFilter.ToLower()); + } + + return false; + }; + } + private List GetDemoDates() { List dates = new List(); @@ -544,7 +760,7 @@ namespace Tango.FSE.Insights.ViewModels } return values; - } + } #endregion } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Views/InsightsView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Views/InsightsView.xaml index dda5861f2..65246662e 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Views/InsightsView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Views/InsightsView.xaml @@ -13,243 +13,370 @@ mc:Ignorable="d" d:DesignHeight="1080" d:DesignWidth="1920" d:DataContext="{d:DesignInstance Type=vm:InsightsViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.InsightsViewVM}"> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + Insights + + Welcome to the Insights module + + This module allows you to collect, view and analyze important machine data using interactive charts and annotations. + + + + Use the search panel above to select target dates for data collection, then press 'Get Insights'. + + + Toggle the settings panel on the left to configure your workspace. + + + + The workspace supports panning and zooming. + Hold and drag the mouse to pan the charts, or hold the Ctrl key to zoom. + + + + + Insights available ! + Use the pane on the left to select monitors to display. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/app.config b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/app.config index 36bc04f85..391504c17 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/app.config +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/app.config @@ -12,7 +12,7 @@ - + @@ -52,7 +52,7 @@ - + @@ -74,6 +74,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/packages.config b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/packages.config index dd8c723e4..e06be2064 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/packages.config +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/packages.config @@ -6,5 +6,19 @@ - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/IInsightsProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/IInsightsProvider.cs index f90e398fd..28af42d5f 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/IInsightsProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/IInsightsProvider.cs @@ -8,6 +8,7 @@ namespace Tango.FSE.Common.Insights { public interface IInsightsProvider { + Task GetInsightsMinDate(); Task GetInsights(DateTime startDateUTC, DateTime endTimeUTC); } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.config b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.config index 60973a611..ed0662bd0 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.config +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.config @@ -82,7 +82,15 @@ - + + + + + + + + + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs index 0f0531bce..1ddf0fa22 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs @@ -12,12 +12,14 @@ using Tango.FSE.Common.FileSystem; using Tango.FSE.Common.Insights; using Tango.Insights; using Tango.PPC.Shared.Insights; +using Tango.Transport; namespace Tango.FSE.UI.Insights { public class DefaultInsightsProvider : ExtendedObject, IInsightsProvider { - [TangoInject] + private DateTime? minDate; + private IMachineProvider MachineProvider { get; set; } [TangoInject] @@ -26,6 +28,17 @@ namespace Tango.FSE.UI.Insights [TangoInject] private FSEServicesContainer Services { get; set; } + public DefaultInsightsProvider(IMachineProvider machineProvider) + { + MachineProvider = machineProvider; + MachineProvider.MachineDisconnected += MachineProvider_MachineDisconnected; + } + + private void MachineProvider_MachineDisconnected(object sender, MachineDisconnectedEventArgs e) + { + minDate = null; + } + public async Task GetInsights(DateTime startDateUTC, DateTime endTimeUTC) { InsightsHandler handler = null; @@ -126,6 +139,17 @@ namespace Tango.FSE.UI.Insights { handler.RaiseFailed(ex); } + finally + { + try + { + var result = MachineProvider.MachineOperator.SendGenericRequest(new InsightsDownloadCompletedRequest() + { + InisightsFilePath = response.InisightsFilePath + }).Result; + } + catch { } + } }); } else if (status == FileSystemHandlerStatus.Failed) @@ -142,5 +166,21 @@ namespace Tango.FSE.UI.Insights return handler; } + + public async Task GetInsightsMinDate() + { + if (minDate != null) + { + return minDate; + } + + var response = await MachineProvider.MachineOperator.SendGenericRequest(new InsightsMinDateRequest(), new TransportRequestConfig() + { + Timeout = TimeSpan.FromSeconds(10) + }); + + minDate = response.MinDate; + return minDate; + } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj index 24cbfd55f..8974407d4 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj @@ -130,8 +130,8 @@ ..\..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll - - ..\..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + + ..\..\packages\System.Collections.Immutable.1.7.1\lib\net461\System.Collections.Immutable.dll diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config b/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config index 4fda0a885..acd5512bc 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config @@ -21,7 +21,7 @@ - + diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml index d436c58b7..3e7162616 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml @@ -345,12 +345,12 @@ Insights Storage Cleanup Interval (min) - + Insights Max Storage Duration (days) - + diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/EventLogging/DefaultEventLogger.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/EventLogging/DefaultEventLogger.cs index ade15af7b..841dfa4fc 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/EventLogging/DefaultEventLogger.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/EventLogging/DefaultEventLogger.cs @@ -104,14 +104,22 @@ namespace Tango.PPC.Common.EventLogging foreach (var type in _db.EventTypes) { - _eventTypesGuids.Add((EventTypes)type.Code, type); + try + { + _eventTypesGuids.Add((EventTypes)type.Code, type); + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error initializing event type '{type.Name}'."); + } } _isInitialized = true; } - catch + catch (Exception ex) { _isInitialized = false; + LogManager.Log(ex, "Error initializing event types."); } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs index fbe606af9..f015c3bad 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs @@ -39,6 +39,7 @@ namespace Tango.PPC.Common.Insights try { var settings = SettingsManager.Default.GetOrCreate(); + settings.Save(); if (settings.InsightsEnabled) { @@ -103,6 +104,43 @@ namespace Tango.PPC.Common.Insights } } + [ExternalBridgeRequestHandlerMethod(typeof(InsightsDownloadCompletedRequest), RequestHandlerLoggingMode.LogRequestName)] + public async Task OnInsightsDownloadCompletedRequest(InsightsDownloadCompletedRequest request, String token, ExternalBridgeReceiver receiver) + { + await Task.Factory.StartNew(() => + { + try + { + File.Delete(request.InisightsFilePath); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error deleting insights request temp file after download completion."); + } + }); + await receiver.SendGenericResponse(new InsightsResponse(), token); + } + + [ExternalBridgeRequestHandlerMethod(typeof(InsightsMinDateRequest), RequestHandlerLoggingMode.LogRequestName)] + public async Task OnInsightsMinDateRequest(InsightsMinDateRequest request, String token, ExternalBridgeReceiver receiver) + { + DateTime? minDate = null; + + try + { + await Task.Factory.StartNew(() => + { + minDate = InsightsManager.Default.GetFramesMinDate(); + }); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error retrieving insights frames minimum date."); + } + + await receiver.SendGenericResponse(new InsightsMinDateResponse() { MinDate = minDate }, token); + } + public void OnReceiverDisconnected(ExternalBridgeReceiver receiver) { //Do Nothing... diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsDownloadCompletedRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsDownloadCompletedRequest.cs new file mode 100644 index 000000000..f298f6a6b --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsDownloadCompletedRequest.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.PPC.Shared.Insights +{ + public class InsightsDownloadCompletedRequest + { + public String InisightsFilePath { get; set; } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsDownloadCompletedResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsDownloadCompletedResponse.cs new file mode 100644 index 000000000..04fd3d1b9 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsDownloadCompletedResponse.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.PPC.Shared.Insights +{ + public class InsightsDownloadCompletedResponse + { + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsMinDateRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsMinDateRequest.cs new file mode 100644 index 000000000..1bb70c396 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsMinDateRequest.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.PPC.Shared.Insights +{ + public class InsightsMinDateRequest + { + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsMinDateResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsMinDateResponse.cs new file mode 100644 index 000000000..7d0e0db84 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsMinDateResponse.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.PPC.Shared.Insights +{ + public class InsightsMinDateResponse + { + public DateTime? MinDate { get; set; } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj index cc39c8746..de1eb03b1 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj +++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj @@ -65,6 +65,10 @@ + + + + diff --git a/Software/Visual_Studio/Tango.Core/ExtensionMethods/ListExtensions.cs b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ListExtensions.cs new file mode 100644 index 000000000..f3e57b3ea --- /dev/null +++ b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ListExtensions.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + +public static class ListExtensions +{ + /// + /// Splits the list to chunks. + /// + /// + /// The source. + /// Size of the chunk. + /// + public static List> ChunkBy(this List source, int chunkSize) + { + return source + .Select((x, i) => new { Index = i, Value = x }) + .GroupBy(x => x.Index / chunkSize) + .Select(x => x.Select(v => v.Value).ToList()) + .ToList(); + } +} + diff --git a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj index ef8ab0a30..2db9c8643 100644 --- a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj +++ b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj @@ -100,6 +100,7 @@ + @@ -215,7 +216,7 @@ - + diff --git a/Software/Visual_Studio/Tango.Insights/InsightsManager.cs b/Software/Visual_Studio/Tango.Insights/InsightsManager.cs index b0c7b78ac..73b74bff6 100644 --- a/Software/Visual_Studio/Tango.Insights/InsightsManager.cs +++ b/Software/Visual_Studio/Tango.Insights/InsightsManager.cs @@ -105,7 +105,21 @@ namespace Tango.Insights return collection.DeleteMany(x => x.Time < maxDateUTC); } - public virtual List GetEvents(DateTime startUTC, DateTime endUTC) + public DateTime? GetFramesMinDate() + { + var collection = GetInsightsCollection(); + + if (collection.Count() > 0) + { + return collection.Min(x => x.Time); + } + else + { + return null; + } + } + + public virtual List GetEvents(DateTime startUTC, DateTime endUTC, bool limitToMinFramesTime = true) { using (ObservablesContext db = ObservablesContext.CreateDefault()) { @@ -128,6 +142,17 @@ namespace Tango.Insights .OrderBy(x => x.Time) .ToList(); + if (limitToMinFramesTime) + { + var collection = GetInsightsCollection(); + + if (collection.Count() > 0) + { + var minTime = collection.Min(x => x.Time); + events.RemoveAll(x => x.Time < minTime); + } + } + return events; } } -- cgit v1.3.1 From a9b1c4cb5c4d945565e72e80ac0f938a49da3e5f Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Sat, 22 Aug 2020 05:15:57 +0300 Subject: Implemented pre-connection protocol configuration. Improved error handling across transport layer. Improved unexpected app crash for PPC. Improved transporter request received handlers tunneling. --- Software/PMR/Messages/Common/MessageType.proto | 2 + .../Integration/ConfigureProtocolRequest.proto | 12 ++ .../Integration/ConfigureProtocolResponse.proto | 9 + .../ExternalBridgeUdpDiscoveryPacket.proto | 1 - .../Integration/GenericMessageProtocol.proto | 11 ++ .../FSE/Tango.FSE.Common/Resources/Converters.xaml | 1 + .../Connection/DefaultMachineProvider.cs | 13 +- .../FileSystem/DefaultFileSystemProvider.cs | 3 +- .../Insights/DefaultInsightsProvider.cs | 2 +- .../Tango.FSE.UI/Panes/ConnectedMachinePane.xaml | 6 +- .../Views/ConnectedMachineView.xaml | 10 ++ .../Tango.PPC.MachineSettings/Views/MainView.xaml | 6 +- .../ExternalBridge/PPCExternalBridgeService.cs | 2 +- .../FileSystem/DefaultFileSystemService.cs | 8 +- .../PPC/Tango.PPC.Common/PPCSettings.cs | 7 +- Software/Visual_Studio/PPC/Tango.PPC.UI/App.config | 4 +- .../Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs | 16 +- .../Visual_Studio/Tango.Emulations/EmulatorBase.cs | 2 +- .../Tango.Emulations/Emulators/MachineEmulator.cs | 4 +- .../Tango.Emulations/Emulators/MobileEmulator.cs | 4 +- .../ExternalBridge/ExternalBridgeReceiver.cs | 23 ++- .../ExternalBridge/ExternalBridgeScanner.cs | 4 +- .../ExternalBridge/ExternalBridgeService.cs | 86 +++++----- .../ExternalBridge/ExternalBridgeSignalRClient.cs | 43 +++-- .../ExternalBridge/ExternalBridgeTcpClient.cs | 65 ++++--- .../ExternalBridge/IExternalBridgeClient.cs | 5 - .../ExternalBridge/IExternalBridgeSecureClient.cs | 5 +- .../ExternalBridge/IExternalBridgeService.cs | 5 - .../ExternalBridge/Web/MachineInfo.cs | 3 +- .../Tango.Integration/Operation/MachineOperator.cs | 10 +- .../Tango.Logging/GlobalExceptionTrapper.cs | 1 - .../Visual_Studio/Tango.PMR/Common/MessageType.cs | 179 +++++++++---------- .../Integration/ConfigureProtocolRequest.cs | 190 +++++++++++++++++++++ .../Integration/ConfigureProtocolResponse.cs | 160 +++++++++++++++++ .../ExternalBridgeUdpDiscoveryPacket.cs | 35 +--- .../Integration/GenericMessageProtocol.cs | 47 +++++ Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj | 5 +- .../GenericMessageProtocolToStringConverter.cs | 42 +++++ .../Converters/StringToOneLineConverter.cs | 2 +- .../Tango.SharedUI/Tango.SharedUI.csproj | 7 +- .../Adapters/SignalRTransportAdapter.cs | 63 ++++--- .../Adapters/TcpTransportAdapter.cs | 16 +- .../Tango.Transport/GenericMessageSerializer.cs | 62 +++---- .../Visual_Studio/Tango.Transport/ITransporter.cs | 8 +- .../Tango.Transport/RequestReceivedEventArgs.cs | 25 +++ .../Tango.Transport/Tango.Transport.csproj | 3 +- .../Tango.Transport/TransportAdapterBase.cs | 7 +- .../Tango.Transport/TransporterBase.cs | 57 +++++-- .../Tango.WebRTC/WebRtcTransportAdapter.cs | 87 ++++++---- 49 files changed, 999 insertions(+), 369 deletions(-) create mode 100644 Software/PMR/Messages/Integration/ConfigureProtocolRequest.proto create mode 100644 Software/PMR/Messages/Integration/ConfigureProtocolResponse.proto create mode 100644 Software/PMR/Messages/Integration/GenericMessageProtocol.proto create mode 100644 Software/Visual_Studio/Tango.PMR/Integration/ConfigureProtocolRequest.cs create mode 100644 Software/Visual_Studio/Tango.PMR/Integration/ConfigureProtocolResponse.cs create mode 100644 Software/Visual_Studio/Tango.PMR/Integration/GenericMessageProtocol.cs create mode 100644 Software/Visual_Studio/Tango.SharedUI/Converters/GenericMessageProtocolToStringConverter.cs create mode 100644 Software/Visual_Studio/Tango.Transport/RequestReceivedEventArgs.cs (limited to 'Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings') diff --git a/Software/PMR/Messages/Common/MessageType.proto b/Software/PMR/Messages/Common/MessageType.proto index e9146cc5f..4f2147b02 100644 --- a/Software/PMR/Messages/Common/MessageType.proto +++ b/Software/PMR/Messages/Common/MessageType.proto @@ -146,6 +146,8 @@ enum MessageType UpdateStatusResponse = 1016; GenericRequest = 1017; GenericResponse = 1018; + ConfigureProtocolRequest = 1019; + ConfigureProtocolResponse = 1020; diff --git a/Software/PMR/Messages/Integration/ConfigureProtocolRequest.proto b/Software/PMR/Messages/Integration/ConfigureProtocolRequest.proto new file mode 100644 index 000000000..850df63de --- /dev/null +++ b/Software/PMR/Messages/Integration/ConfigureProtocolRequest.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +import "GenericMessageProtocol.proto"; + +package Tango.PMR.Integration; +option java_package = "com.twine.tango.pmr.integration"; + +message ConfigureProtocolRequest +{ + bool EnableCompression = 1; + GenericMessageProtocol GenericProtocol = 2; +} \ No newline at end of file diff --git a/Software/PMR/Messages/Integration/ConfigureProtocolResponse.proto b/Software/PMR/Messages/Integration/ConfigureProtocolResponse.proto new file mode 100644 index 000000000..1f32296da --- /dev/null +++ b/Software/PMR/Messages/Integration/ConfigureProtocolResponse.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +package Tango.PMR.Integration; +option java_package = "com.twine.tango.pmr.integration"; + +message ConfigureProtocolResponse +{ + bool Confirmed = 1; +} \ No newline at end of file diff --git a/Software/PMR/Messages/Integration/ExternalBridgeUdpDiscoveryPacket.proto b/Software/PMR/Messages/Integration/ExternalBridgeUdpDiscoveryPacket.proto index 4a7d5b59b..d797e6de3 100644 --- a/Software/PMR/Messages/Integration/ExternalBridgeUdpDiscoveryPacket.proto +++ b/Software/PMR/Messages/Integration/ExternalBridgeUdpDiscoveryPacket.proto @@ -7,5 +7,4 @@ message ExternalBridgeUdpDiscoveryPacket { string Time = 1; string SerialNumber = 2; - bool CompressionEnabled = 3; } \ No newline at end of file diff --git a/Software/PMR/Messages/Integration/GenericMessageProtocol.proto b/Software/PMR/Messages/Integration/GenericMessageProtocol.proto new file mode 100644 index 000000000..cb6021944 --- /dev/null +++ b/Software/PMR/Messages/Integration/GenericMessageProtocol.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +package Tango.PMR.Integration; +option java_package = "com.twine.tango.pmr.integration"; + +enum GenericMessageProtocol +{ + Json = 0; + Bson = 1; + Protobuf = 2; +} \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml index 922790d5e..83481a9d7 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml @@ -45,4 +45,5 @@ + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs index 55866361b..f6bbaab87 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs @@ -24,6 +24,7 @@ using Tango.FSE.UI.Dialogs; using Tango.Integration.ExternalBridge; using Tango.Integration.Operation; using Tango.Logging; +using Tango.PMR.Integration; using Tango.SharedUI; using Tango.Transport; @@ -162,7 +163,7 @@ namespace Tango.FSE.UI.Connection { _machineEventsStateProvider = new FSEMachineEventsStateProvider(); - MachineOperator = new ExternalBridgeTcpClient("N/A", "N/A", false); + MachineOperator = new ExternalBridgeTcpClient("N/A", "N/A"); MachineOperator.MachineEventsStateProvider = _machineEventsStateProvider; MachineOperator.StateChanged += MachineOperator_StateChanged; MachineOperator.As().SessionClosed += DefaultMachineProvider_SessionClosed; @@ -185,7 +186,7 @@ namespace Tango.FSE.UI.Connection { try { - LogManager.Log($"Connecting to machine '{machine.GetType().Name}' => '{machine.SerialNumber}' => '{machine.Adapter?.Address}' => {(machine.CompressionEnabled ? "Compression Enabled" : "Compression Disabled")}..."); + LogManager.Log($"Connecting to machine '{machine.GetType().Name}' => '{machine.SerialNumber}' => '{machine.Adapter?.Address}'..."); IsBusy = true; @@ -214,7 +215,7 @@ namespace Tango.FSE.UI.Connection vm = await NotificationProvider.ShowDialog(new MachineConnectionSignalRViewVM(secureClient)); } - secureClient.LoginRequest = new PMR.Integration.ExternalBridgeLoginRequest() + secureClient.LoginRequest = new ExternalBridgeLoginRequest() { AppID = "Tango FSE", HostName = Environment.MachineName, @@ -225,6 +226,12 @@ namespace Tango.FSE.UI.Connection UserName = AuthenticationProvider.CurrentUser.Contact.FullName }; + secureClient.ConfigureProtocolRequest = new ConfigureProtocolRequest() + { + EnableCompression = true, + GenericProtocol = GenericMessageProtocol.Bson + }; + LogManager.Log($"Target machine requires a secure connection. Login Request:\n{secureClient.LoginRequest.ToJsonString()}"); } else diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs index e7f9772ff..2e3ffec19 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs @@ -169,9 +169,10 @@ namespace Tango.FSE.UI.FileSystem _webRtcTransporter = new BasicTransporter(new WebRtcTransportAdapter(_machineProvider.MachineOperator, WebRtcTransportAdapterMode.Active, WEB_RTC_CHANNEL_NAME) { - EnableCompression = _machineProvider.MachineOperator.CompressionEnabled, + EnableCompression = _machineProvider.MachineOperator.Adapter.EnableCompression, }); _webRtcTransporter.UseKeepAlive = false; + _webRtcTransporter.GenericProtocol = _machineProvider.MachineOperator.GenericProtocol; _webRtcTransporter.ComponentName = "File System Active WebRTC Transporter"; await _webRtcTransporter.Connect(); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs index 1ddf0fa22..a4958f25d 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs @@ -47,7 +47,7 @@ namespace Tango.FSE.UI.Insights { StartDateUTC = startDateUTC, EndDateUTC = endTimeUTC - }, new Transport.TransportRequestConfig() + }, new TransportRequestConfig() { Timeout = TimeSpan.FromMinutes(1), }); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/ConnectedMachinePane.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/ConnectedMachinePane.xaml index db2559a9d..c0c54b1b6 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/ConnectedMachinePane.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/ConnectedMachinePane.xaml @@ -8,9 +8,11 @@ xmlns:emulations="clr-namespace:Tango.Emulations.ExternalBridge;assembly=Tango.Emulations" xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" xmlns:commonControls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common" + xmlns:localConverters="clr-namespace:Tango.FSE.UI.Converters" xmlns:local="clr-namespace:Tango.FSE.UI.Panes" mc:Ignorable="d" d:DesignHeight="600" d:DesignWidth="350" d:DataContext="{d:DesignInstance Type=local:ConnectedMachinePaneVM, IsDesignTimeCreatable=False}"> +