aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoy Ben Shabat <Roy.mail.net@gmail.com>2020-04-17 06:12:39 +0300
committerRoy Ben Shabat <Roy.mail.net@gmail.com>2020-04-17 06:12:39 +0300
commitf41d7e0a4457c0e894f53f5c9c866b8588f67eab (patch)
tree678fa2f1c21a0d6418eeb2cc0270066dce971f32
parentd6b5c18d94c70679f92fd54d95de1d39f355c0b7 (diff)
downloadTango-f41d7e0a4457c0e894f53f5c9c866b8588f67eab.tar.gz
Tango-f41d7e0a4457c0e894f53f5c9c866b8588f67eab.zip
Beit Hakodesh !
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Controls/DiagnosticsGrid.cs49
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/DiagnosticsWidgetToViewConverter.cs31
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/DiagnosticsPackage.cs81
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProject.cs55
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProjectTab.cs27
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProjectTabColumnDefinition.cs14
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProjectTabRowDefinition.cs14
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsWidget.cs63
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidget.cs66
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.xaml13
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.xaml.cs28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Tango.FSE.Diagnostics.csproj46
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModelLocator.cs9
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsTabViewVM.cs29
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs102
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsTabView.xaml40
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsTabView.xaml.cs28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsView.xaml108
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsView.xaml.cs28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/MainView.xaml4
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Tango.FSE.Firmware.csproj1
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj1
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Tango.FSE.Upgrade.csproj1
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/CacheManager.cs40
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/DiskCacheManager.cs57
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/EntityRepositoryBase.cs137
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServiceBase.cs12
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs6
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/IMemoryCacheDictionary.cs29
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/MemoryCacheDictionary.cs218
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/MemoryCacheManager.cs92
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/ReadOnlyEntityRepository.cs42
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/Services/MachinesService.cs29
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/Services/TangoVersionsService.cs7
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/Services/TechComponentsService.cs44
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj17
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/packages.config4
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Diagnostics/DiagnosticsFrame.cs20
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Diagnostics/DefaultDiagnosticsProvider.cs17
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs2
-rw-r--r--Software/Visual_Studio/Tango.Scripting/ExpressionGenerator.cs22
-rw-r--r--Software/Visual_Studio/Tango.Scripting/Tango.Scripting.csproj3
-rw-r--r--Software/Visual_Studio/Tango.WebRTC/WebRtcTransportAdapter.cs20
43 files changed, 1586 insertions, 70 deletions
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Controls/DiagnosticsGrid.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Controls/DiagnosticsGrid.cs
new file mode 100644
index 000000000..45b6d9a36
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Controls/DiagnosticsGrid.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using Tango.FSE.Diagnostics.Project;
+
+namespace Tango.FSE.Diagnostics.Controls
+{
+ public class DiagnosticsGrid : Grid
+ {
+ public List<DiagnosticsProjectTabColumnDefinition> Columns
+ {
+ get { return (List<DiagnosticsProjectTabColumnDefinition>)GetValue(ColumnsProperty); }
+ set { SetValue(ColumnsProperty, value); }
+ }
+ public static readonly DependencyProperty ColumnsProperty =
+ DependencyProperty.Register("Columns", typeof(List<DiagnosticsProjectTabColumnDefinition>), typeof(DiagnosticsGrid), new PropertyMetadata(null, (d, e) => (d as DiagnosticsGrid).LoadDefinitions()));
+
+ public List<DiagnosticsProjectTabRowDefinition> Rows
+ {
+ get { return (List<DiagnosticsProjectTabRowDefinition>)GetValue(RowsProperty); }
+ set { SetValue(RowsProperty, value); }
+ }
+ public static readonly DependencyProperty RowsProperty =
+ DependencyProperty.Register("Rows", typeof(List<DiagnosticsProjectTabRowDefinition>), typeof(DiagnosticsGrid), new PropertyMetadata(null, (d, e) => (d as DiagnosticsGrid).LoadDefinitions()));
+
+ private void LoadDefinitions()
+ {
+ if (Rows != null && Columns != null)
+ {
+ ColumnDefinitions.Clear();
+ RowDefinitions.Clear();
+
+ foreach (var column in Columns)
+ {
+ ColumnDefinitions.Add(new ColumnDefinition() { Width = column.Width });
+ }
+
+ foreach (var row in Rows)
+ {
+ RowDefinitions.Add(new RowDefinition() { Height = row.Height });
+ }
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/DiagnosticsWidgetToViewConverter.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/DiagnosticsWidgetToViewConverter.cs
new file mode 100644
index 000000000..439b1a17a
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/DiagnosticsWidgetToViewConverter.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+using Tango.FSE.Diagnostics.Project;
+
+namespace Tango.FSE.Diagnostics.Converters
+{
+ public class DiagnosticsWidgetToViewConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ DiagnosticsWidget widget = value as DiagnosticsWidget;
+
+ if (widget != null)
+ {
+ return widget.GetView();
+ }
+
+ return null;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/DiagnosticsPackage.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/DiagnosticsPackage.cs
new file mode 100644
index 000000000..48fe8c186
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/DiagnosticsPackage.cs
@@ -0,0 +1,81 @@
+using Google.Protobuf.Collections;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.Enumerations;
+using Tango.FSE.Common.Diagnostics;
+using Tango.PMR.Diagnostics;
+
+namespace Tango.FSE.Diagnostics
+{
+ public class DiagnosticsPackage
+ {
+ /// <summary>
+ /// Gets or sets the frame.
+ /// </summary>
+ public DiagnosticsFrame Frame { get; set; }
+
+ /// <summary>
+ /// Gets or sets the monitors properties.
+ /// </summary>
+ public Dictionary<String, PropertyInfo> MonitorsProperties { get; set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DiagnosticsPackage"/> class.
+ /// </summary>
+ public DiagnosticsPackage()
+ {
+ MonitorsProperties = new Dictionary<string, PropertyInfo>();
+ }
+
+ /// <summary>
+ /// Gets the monitor value by the specified monitor using reflections.
+ /// </summary>
+ /// <param name="monitor">The monitor.</param>
+ /// <returns></returns>
+ public object GetMonitorObject(TechMonitors monitor)
+ {
+ return MonitorsProperties[monitor.ToString()].GetValue(Frame.Data.Monitors);
+ }
+
+ /// <summary>
+ /// Gets the last data point from a protobuf repeated field.
+ /// </summary>
+ /// <param name="monitor">The monitor.</param>
+ /// <param name="value">The value.</param>
+ /// <returns></returns>
+ public double GetMonitorLastValue(TechMonitors monitor)
+ {
+ var value = GetMonitorObject(monitor);
+ RepeatedField<double> arr = value as RepeatedField<double>;
+ return arr.LastOrDefault();
+ }
+
+ /// <summary>
+ /// Gets the data array from a protobuf repeated field.
+ /// </summary>
+ /// <param name="monitor">The monitor.</param>
+ /// <param name="value">The value.</param>
+ /// <returns></returns>
+ public List<double> GetMonitorArray(TechMonitors monitor)
+ {
+ var value = GetMonitorObject(monitor);
+ return (value as RepeatedField<double>).ToList();
+ }
+
+ /// <summary>
+ /// Gets the data matrix from a protobuf repeated field of <see cref="DoubleArray"/>.
+ /// </summary>
+ /// <param name="monitor">The monitor.</param>
+ /// <returns></returns>
+ public List<List<double>> GetMonitorMatrix(TechMonitors monitor)
+ {
+ var value = GetMonitorObject(monitor);
+ DoubleArray[] arrayOfDoubles = Enumerable.ToArray(value as IEnumerable<DoubleArray>);
+ return arrayOfDoubles.Select(x => x.Data.ToList()).ToList();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProject.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProject.cs
new file mode 100644
index 000000000..bc93f4101
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProject.cs
@@ -0,0 +1,55 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core;
+
+namespace Tango.FSE.Diagnostics.Project
+{
+ public class DiagnosticsProject : ExtendedObject
+ {
+ private static JsonSerializerSettings _settings;
+
+ public String Name { get; set; }
+ public ObservableCollection<DiagnosticsProjectTab> Tabs { get; set; }
+
+ static DiagnosticsProject()
+ {
+ _settings = new JsonSerializerSettings()
+ {
+ TypeNameHandling = TypeNameHandling.Auto,
+ Formatting = Formatting.Indented
+ };
+ }
+
+ public DiagnosticsProject()
+ {
+ Name = "Diagnostics Project";
+ Tabs = new ObservableCollection<DiagnosticsProjectTab>();
+ }
+
+ public String ToJson()
+ {
+ return JsonConvert.SerializeObject(this, _settings);
+ }
+
+ public static DiagnosticsProject FromJson(String json)
+ {
+ return JsonConvert.DeserializeObject<DiagnosticsProject>(json, _settings);
+ }
+
+ public void ToFile(String fileName)
+ {
+ File.WriteAllText(fileName, ToJson());
+ }
+
+ public static DiagnosticsProject FromFile(String fileName)
+ {
+ return FromJson(File.ReadAllText(fileName));
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProjectTab.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProjectTab.cs
new file mode 100644
index 000000000..d50a6aa0d
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProjectTab.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using Tango.Core;
+using Tango.FSE.Diagnostics.Project.Widgets;
+
+namespace Tango.FSE.Diagnostics.Project
+{
+ public class DiagnosticsProjectTab : ExtendedObject
+ {
+ public String Name { get; set; }
+ public List<DiagnosticsProjectTabColumnDefinition> Columns { get; set; }
+ public List<DiagnosticsProjectTabRowDefinition> Rows { get; set; }
+ public ObservableCollection<DiagnosticsWidget> Widgets { get; set; }
+
+ public DiagnosticsProjectTab()
+ {
+ Columns = new List<DiagnosticsProjectTabColumnDefinition>();
+ Rows = new List<DiagnosticsProjectTabRowDefinition>();
+ Widgets = new ObservableCollection<DiagnosticsWidget>();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProjectTabColumnDefinition.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProjectTabColumnDefinition.cs
new file mode 100644
index 000000000..3f10fa793
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProjectTabColumnDefinition.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace Tango.FSE.Diagnostics.Project
+{
+ public class DiagnosticsProjectTabColumnDefinition
+ {
+ public GridLength Width { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProjectTabRowDefinition.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProjectTabRowDefinition.cs
new file mode 100644
index 000000000..0797d89ac
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsProjectTabRowDefinition.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace Tango.FSE.Diagnostics.Project
+{
+ public class DiagnosticsProjectTabRowDefinition
+ {
+ public GridLength Height { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsWidget.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsWidget.cs
new file mode 100644
index 000000000..4689af541
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsWidget.cs
@@ -0,0 +1,63 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using Tango.Core;
+using Tango.Core.DI;
+using Tango.FSE.BL;
+using Tango.FSE.Common.Authentication;
+using Tango.FSE.Common.Connection;
+using Tango.FSE.Common.Notifications;
+using Tango.PMR.Diagnostics;
+
+namespace Tango.FSE.Diagnostics.Project
+{
+ public abstract class DiagnosticsWidget : ExtendedObject
+ {
+ [JsonIgnore]
+ [TangoInject(TangoInjectMode.WhenAvailable)]
+ protected IAuthenticationProvider AuthenticationProvider { get; set; }
+
+ [JsonIgnore]
+ [TangoInject(TangoInjectMode.WhenAvailable)]
+ protected IMachineProvider MachineProvider { get; set; }
+
+ [JsonIgnore]
+ [TangoInject(TangoInjectMode.WhenAvailable)]
+ protected INotificationProvider NotificationProvider { get; set; }
+
+ private FSEServicesContainer _services;
+ [JsonIgnore]
+ [TangoInject(TangoInjectMode.WhenAvailable)]
+ public FSEServicesContainer Services
+ {
+ get { return _services; }
+ set { _services = value; OnServicesAvailable(); }
+ }
+
+ public int Column { get; set; }
+ public int Row { get; set; }
+ public int ColumnSpan { get; set; }
+ public int RowSpan { get; set; }
+
+ public DiagnosticsWidget()
+ {
+ TangoIOC.Default.Inject(this);
+ }
+
+ protected virtual void OnServicesAvailable()
+ {
+
+ }
+
+ public virtual void OnDiagnosticsData(DiagnosticsPackage package)
+ {
+ //Called when diagnostics data is available
+ }
+
+ public abstract FrameworkElement GetView();
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidget.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidget.cs
new file mode 100644
index 000000000..bc7b38a1c
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidget.cs
@@ -0,0 +1,66 @@
+using Newtonsoft.Json;
+using RealTimeGraphX.DataPoints;
+using RealTimeGraphX.WPF;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media;
+using Tango.BL.Enumerations;
+
+namespace Tango.FSE.Diagnostics.Project.Widgets
+{
+ public class RealTimeGraphWidget : DiagnosticsWidget
+ {
+ public TechMonitors Monitor { get; set; } = TechMonitors.Dancer2Angle;
+
+ [JsonIgnore]
+ public WpfGraphController<TimeSpanDataPoint, DoubleDataPoint> Controller { get; set; }
+
+ public RealTimeGraphWidget()
+ {
+ Controller = new WpfGraphController<TimeSpanDataPoint, DoubleDataPoint>();
+ Controller.Range.AutoY = true;
+ Controller.Range.MaximumX = TimeSpan.FromSeconds(60);
+ Controller.RefreshRate = TimeSpan.FromMilliseconds(100);
+
+ Controller.DataSeriesCollection.Add(new WpfGraphDataSeries()
+ {
+ Stroke = Colors.DodgerBlue
+ });
+ }
+
+ public override FrameworkElement GetView()
+ {
+ return new RealTimeGraphWidgetView() { DataContext = this };
+ }
+
+ public override void OnDiagnosticsData(DiagnosticsPackage package)
+ {
+ base.OnDiagnosticsData(package);
+ var points = package.GetMonitorArray(Monitor);
+
+ if (points.Count > 0)
+ {
+ List<TimeSpanDataPoint> dates = new List<TimeSpanDataPoint>();
+ var dPoints = points.Select(x => new DoubleDataPoint(x)).ToList();
+
+ DateTime dayStart = new DateTime(package.Frame.DiagnosticsTime.Year, package.Frame.DiagnosticsTime.Month, package.Frame.DiagnosticsTime.Day);
+ TimeSpan offset = package.Frame.DiagnosticsTime - dayStart;
+
+ for (int i = 0; i < points.Count; i++)
+ {
+ dates.Add(
+ offset
+ .Add(TimeSpan.FromMilliseconds(-package.Frame.Delta.TotalMilliseconds))
+ .Add(TimeSpan.FromMilliseconds(package.Frame.Delta.TotalMilliseconds * (i / (double)points.Count))));
+ }
+
+ Controller.PushData(dates, dPoints);
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.xaml
new file mode 100644
index 000000000..7c6eb92d3
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.xaml
@@ -0,0 +1,13 @@
+<UserControl x:Class="Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphWidgetView"
+ 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:local="clr-namespace:Tango.FSE.Diagnostics.Project.Widgets"
+ xmlns:graphs="clr-namespace:Tango.FSE.Common.Graphs;assembly=Tango.FSE.Common"
+ mc:Ignorable="d"
+ d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=local:RealTimeGraphWidget,IsDesignTimeCreatable=False}">
+ <Grid>
+ <graphs:RealTimeGraph Controller="{Binding Controller}" />
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.xaml.cs
new file mode 100644
index 000000000..546a55f74
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.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.Diagnostics.Project.Widgets
+{
+ /// <summary>
+ /// Interaction logic for RealTimeGraphWidgetView.xaml
+ /// </summary>
+ public partial class RealTimeGraphWidgetView : UserControl
+ {
+ public RealTimeGraphWidgetView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Tango.FSE.Diagnostics.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Tango.FSE.Diagnostics.csproj
index 26b419103..371cdc6b5 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Tango.FSE.Diagnostics.csproj
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Tango.FSE.Diagnostics.csproj
@@ -24,6 +24,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -78,9 +79,29 @@
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="Controls\DiagnosticsGrid.cs" />
+ <Compile Include="Converters\DiagnosticsWidgetToViewConverter.cs" />
+ <Compile Include="DiagnosticsPackage.cs" />
+ <Compile Include="Project\DiagnosticsProject.cs" />
+ <Compile Include="Project\DiagnosticsProjectTab.cs" />
+ <Compile Include="Project\DiagnosticsProjectTabColumnDefinition.cs" />
+ <Compile Include="Project\DiagnosticsProjectTabRowDefinition.cs" />
+ <Compile Include="Project\DiagnosticsWidget.cs" />
+ <Compile Include="Project\Widgets\RealTimeGraphWidget.cs" />
+ <Compile Include="Project\Widgets\RealTimeGraphWidgetView.xaml.cs">
+ <DependentUpon>RealTimeGraphWidgetView.xaml</DependentUpon>
+ </Compile>
<Compile Include="ViewModelLocator.cs" />
<Compile Include="DiagnosticsModule.cs" />
+ <Compile Include="ViewModels\DiagnosticsTabViewVM.cs" />
+ <Compile Include="ViewModels\DiagnosticsViewVM.cs" />
<Compile Include="ViewModels\MainViewVM.cs" />
+ <Compile Include="Views\DiagnosticsTabView.xaml.cs">
+ <DependentUpon>DiagnosticsTabView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Views\DiagnosticsView.xaml.cs">
+ <DependentUpon>DiagnosticsView.xaml</DependentUpon>
+ </Compile>
<Compile Include="Views\MainView.xaml.cs">
<DependentUpon>MainView.xaml</DependentUpon>
</Compile>
@@ -103,7 +124,9 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
- <None Include="app.config" />
+ <None Include="app.config">
+ <SubType>Designer</SubType>
+ </None>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
@@ -111,6 +134,14 @@
</None>
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\..\..\SideChains\RealTimeGraphX-master\RealTimeGraphX.WPF\RealTimeGraphX.WPF.csproj">
+ <Project>{6b9774f7-960d-438e-ad81-c6b9be328d50}</Project>
+ <Name>RealTimeGraphX.WPF</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\SideChains\RealTimeGraphX-master\RealTimeGraphX\RealTimeGraphX.csproj">
+ <Project>{f13a489c-80ee-4cd0-bdd4-92d959215646}</Project>
+ <Name>RealTimeGraphX</Name>
+ </ProjectReference>
<ProjectReference Include="..\..\..\SideChains\Tango.AutoComplete\Tango.AutoComplete.csproj">
<Project>{bb2abb74-ba58-4812-83aa-ec8171f42df4}</Project>
<Name>Tango.AutoComplete</Name>
@@ -161,6 +192,18 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
+ <Page Include="Project\Widgets\RealTimeGraphWidgetView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Views\DiagnosticsTabView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Views\DiagnosticsView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Views\MainView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -169,6 +212,7 @@
<ItemGroup>
<Resource Include="Images\diagnostics.png" />
</ItemGroup>
+ <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets" Condition="Exists('..\..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModelLocator.cs
index 6cb3edceb..6048474ef 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModelLocator.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModelLocator.cs
@@ -13,6 +13,7 @@ namespace Tango.FSE.Diagnostics
static ViewModelLocator()
{
TangoIOC.Default.Register<MainViewVM>();
+ TangoIOC.Default.Register<DiagnosticsViewVM>();
}
public static MainViewVM MainViewVM
@@ -22,5 +23,13 @@ namespace Tango.FSE.Diagnostics
return TangoIOC.Default.GetInstance<MainViewVM>();
}
}
+
+ public static DiagnosticsViewVM DiagnosticsViewVM
+ {
+ get
+ {
+ return TangoIOC.Default.GetInstance<DiagnosticsViewVM>();
+ }
+ }
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsTabViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsTabViewVM.cs
new file mode 100644
index 000000000..e3566fd40
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsTabViewVM.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.FSE.Common;
+using Tango.FSE.Diagnostics.Project;
+using Tango.PMR.Diagnostics;
+
+namespace Tango.FSE.Diagnostics.ViewModels
+{
+ public class DiagnosticsTabViewVM : FSEViewModel
+ {
+ private DiagnosticsProjectTab _tab;
+ public DiagnosticsProjectTab Tab
+ {
+ get { return _tab; }
+ set { _tab = value; RaisePropertyChangedAuto(); }
+ }
+
+ public void PopulateDiagnosticsData(DiagnosticsPackage package)
+ {
+ foreach (var widget in Tab.Widgets.ToList())
+ {
+ widget.OnDiagnosticsData(package);
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs
new file mode 100644
index 000000000..f49b9bb15
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.FSE.Common;
+using Tango.FSE.Common.Diagnostics;
+using Tango.FSE.Diagnostics.Project;
+using Tango.PMR.Diagnostics;
+
+namespace Tango.FSE.Diagnostics.ViewModels
+{
+ public class DiagnosticsViewVM : FSEViewModel
+ {
+ private Dictionary<String, PropertyInfo> _monitorsProperties;
+
+ private DiagnosticsProject _project;
+ public DiagnosticsProject Project
+ {
+ get { return _project; }
+ set { _project = value; RaisePropertyChangedAuto(); }
+ }
+
+ private ObservableCollection<DiagnosticsTabViewVM> _tabs;
+
+ public ObservableCollection<DiagnosticsTabViewVM> Tabs
+ {
+ get { return _tabs; }
+ set { _tabs = value; RaisePropertyChangedAuto(); }
+ }
+
+ public DiagnosticsViewVM()
+ {
+ _monitorsProperties = new Dictionary<string, PropertyInfo>();
+
+ foreach (var prop in typeof(DiagnosticsMonitors).GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList())
+ {
+ _monitorsProperties.Add(prop.Name, prop);
+ }
+
+ Tabs = new ObservableCollection<DiagnosticsTabViewVM>();
+ Project = new DiagnosticsProject();
+ }
+
+ public override void OnApplicationStarted()
+ {
+ base.OnApplicationStarted();
+ DiagnosticsProvider.FrameReceived += DiagnosticsProvider_FrameReceived;
+ }
+
+ private void DiagnosticsProvider_FrameReceived(object sender, DiagnosticsFrameReceivedEventArgs e)
+ {
+ PopulateDiagnosticsData(e.Frame);
+ }
+
+ public override void OnApplicationReady()
+ {
+ base.OnApplicationReady();
+ LoadProject();
+ }
+
+ private void LoadProject()
+ {
+ //TODO: Load project...
+ try
+ {
+ Project = DiagnosticsProject.FromFile(Path.Combine(ApplicationManager.StartPath, "diagnostics.json"));
+ }
+ catch (Exception ex)
+ {
+ Project = new DiagnosticsProject();
+ Project.Tabs = new ObservableCollection<DiagnosticsProjectTab>()
+ {
+ new DiagnosticsProjectTab() { Name = "Tab 1" },
+ new DiagnosticsProjectTab() { Name = "Tab 2" },
+ };
+ Project.ToFile(Path.Combine(ApplicationManager.StartPath, "diagnostics.json"));
+ }
+
+ Tabs = new ObservableCollection<DiagnosticsTabViewVM>();
+ foreach (var tab in Project.Tabs)
+ {
+ Tabs.Add(new DiagnosticsTabViewVM() { Tab = tab });
+ }
+ }
+
+ private void PopulateDiagnosticsData(DiagnosticsFrame frame)
+ {
+ foreach (var tab in Tabs.ToList())
+ {
+ tab.PopulateDiagnosticsData(new DiagnosticsPackage()
+ {
+ Frame = frame,
+ MonitorsProperties = _monitorsProperties
+ });
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsTabView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsTabView.xaml
new file mode 100644
index 000000000..52b8a619e
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsTabView.xaml
@@ -0,0 +1,40 @@
+<UserControl x:Class="Tango.FSE.Diagnostics.Views.DiagnosticsTabView"
+ 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.FSE.Diagnostics"
+ xmlns:vm="clr-namespace:Tango.FSE.Diagnostics.ViewModels"
+ xmlns:controls="clr-namespace:Tango.FSE.Diagnostics.Controls"
+ xmlns:local="clr-namespace:Tango.FSE.Diagnostics.Views"
+ xmlns:converters="clr-namespace:Tango.FSE.Diagnostics.Converters"
+ mc:Ignorable="d"
+ d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:DiagnosticsTabViewVM, IsDesignTimeCreatable=False}" Background="{StaticResource FSE_PrimaryBackgroundBrush}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}">
+
+ <UserControl.Resources>
+ <converters:DiagnosticsWidgetToViewConverter x:Key="DiagnosticsWidgetToViewConverter" />
+ </UserControl.Resources>
+
+ <Grid>
+ <ItemsControl ItemsSource="{Binding Tab.Widgets}">
+ <ItemsControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <controls:DiagnosticsGrid IsItemsHost="True" ShowGridLines="True" Columns="{Binding Tab.Columns}" Rows="{Binding Tab.Rows}"/>
+ </ItemsPanelTemplate>
+ </ItemsControl.ItemsPanel>
+ <ItemsControl.ItemContainerStyle>
+ <Style TargetType="FrameworkElement">
+ <Setter Property="Grid.Column" Value="{Binding Column}"></Setter>
+ <Setter Property="Grid.Row" Value="{Binding Row}"></Setter>
+ <Setter Property="Grid.ColumnSpan" Value="{Binding ColumnSpan}"></Setter>
+ <Setter Property="Grid.RowSpan" Value="{Binding RowSpan}"></Setter>
+ </Style>
+ </ItemsControl.ItemContainerStyle>
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <ContentPresenter Content="{Binding Converter={StaticResource DiagnosticsWidgetToViewConverter}}"/>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsTabView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsTabView.xaml.cs
new file mode 100644
index 000000000..e3814dd79
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsTabView.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.Diagnostics.Views
+{
+ /// <summary>
+ /// Interaction logic for DiagnosticsTabView.xaml
+ /// </summary>
+ public partial class DiagnosticsTabView : UserControl
+ {
+ public DiagnosticsTabView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsView.xaml
new file mode 100644
index 000000000..2ae3b9ea7
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsView.xaml
@@ -0,0 +1,108 @@
+<UserControl x:Class="Tango.FSE.Diagnostics.Views.DiagnosticsView"
+ 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.FSE.Diagnostics"
+ xmlns:vm="clr-namespace:Tango.FSE.Diagnostics.ViewModels"
+ xmlns:local="clr-namespace:Tango.FSE.Diagnostics.Views"
+ mc:Ignorable="d"
+ d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:DiagnosticsViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.DiagnosticsViewVM}" Background="{StaticResource FSE_PrimaryBackgroundBrush}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}">
+ <Grid Margin="20">
+ <DockPanel>
+ <Grid DockPanel.Dock="Top" Height="50">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="1*" />
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="1*" />
+ </Grid.ColumnDefinitions>
+ <Rectangle Grid.Column="0" VerticalAlignment="Bottom" StrokeThickness="2" Stroke="{StaticResource FSE_PrimaryAccentDarkBrush}" />
+ <ListBox x:Name="listTabs" Grid.Column="1" DisplayMemberPath="Tag" ItemsSource="{Binding ElementName=tabControl,Path=Items}" SelectedItem="{Binding ElementName=tabControl,Path=SelectedItem,Mode=TwoWay}" SelectedIndex="0">
+ <ListBox.Style>
+ <Style TargetType="ListBox" BasedOn="{StaticResource {x:Type ListBox}}">
+ <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"></Setter>
+ <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"></Setter>
+ <Setter Property="ItemsPanel">
+ <Setter.Value>
+ <ItemsPanelTemplate>
+ <UniformGrid Margin="15 0 0 0" Columns="{Binding RelativeSource={RelativeSource AncestorType=ListBox},Path=Items.Count}" IsItemsHost="True"></UniformGrid>
+ </ItemsPanelTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="ItemContainerStyle">
+ <Setter.Value>
+ <Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
+ <Setter Property="HorizontalContentAlignment" Value="Center"></Setter>
+ <Setter Property="VerticalContentAlignment" Value="Center"></Setter>
+ <Setter Property="Background" Value="{StaticResource FSE_PrimaryBackgroundBrush}"></Setter>
+ <Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource FSE_GrayBrush}"></Setter>
+ <Setter Property="Width" Value="200"></Setter>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="ListBoxItem">
+ <Grid x:Name="grid" Margin="-15 0 0 0" Background="Transparent">
+ <Viewbox Stretch="Fill">
+ <Grid>
+ <Polygon Fill="{TemplateBinding Background}" Stretch="Fill" Points="0,30 15,0 85,0 100,30"></Polygon>
+ <Polygon Fill="White" Stretch="Fill" Points="0,30 15,0 85,0 100,30" IsHitTestVisible="False" Opacity="0.1">
+ <Polygon.Style>
+ <Style TargetType="Polygon">
+ <Setter Property="Visibility" Value="Hidden"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem},Path=IsMouseOver}" Value="True">
+ <Setter Property="Visibility" Value="Visible"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </Polygon.Style>
+ </Polygon>
+ <Polyline Stroke="{StaticResource FSE_PrimaryAccentDarkBrush}" StrokeThickness="1" Stretch="Fill" Points="0,30 15,0 85,0 100,30" />
+ <Rectangle VerticalAlignment="Bottom" Stroke="{StaticResource FSE_PrimaryAccentDarkBrush}" StrokeThickness="1" />
+ </Grid>
+ </Viewbox>
+ <ContentPresenter Content="{Binding Tab.Name}" TextElement.Foreground="{TemplateBinding Foreground}" HorizontalAlignment="Center" VerticalAlignment="Center" />
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsSelected" Value="True">
+
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <Trigger Property="IsSelected" Value="True">
+ <Setter Property="Background" Value="{StaticResource FSE_PrimaryAccentDarkBrush}"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter>
+ <Setter Property="FontWeight" Value="SemiBold"></Setter>
+ <Setter Property="Panel.ZIndex" Value="200"></Setter>
+ </Trigger>
+ <Trigger Property="IsSelected" Value="False">
+ <Setter Property="Panel.ZIndex" Value="-1"></Setter>
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </ListBox.Style>
+ </ListBox>
+ <Rectangle Grid.Column="2" VerticalAlignment="Bottom" StrokeThickness="2" Stroke="{StaticResource FSE_PrimaryAccentDarkBrush}" />
+ </Grid>
+
+ <TabControl x:Name="tabControl" Margin="0 -2 0 0" ItemsSource="{Binding Tabs}" BorderThickness="0" Background="Transparent">
+ <TabControl.ItemContainerStyle>
+ <Style TargetType="TabItem">
+ <Setter Property="Visibility" Value="Collapsed"></Setter>
+ </Style>
+ </TabControl.ItemContainerStyle>
+ <TabControl.ContentTemplate>
+ <DataTemplate>
+ <local:DiagnosticsTabView />
+ </DataTemplate>
+ </TabControl.ContentTemplate>
+ </TabControl>
+ </DockPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsView.xaml.cs
new file mode 100644
index 000000000..553183f96
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsView.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.Diagnostics.Views
+{
+ /// <summary>
+ /// Interaction logic for DiagnosticsView.xaml
+ /// </summary>
+ public partial class DiagnosticsView : UserControl
+ {
+ public DiagnosticsView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/MainView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/MainView.xaml
index e04aaeb98..7733198b4 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/MainView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/MainView.xaml
@@ -7,8 +7,8 @@
xmlns:vm="clr-namespace:Tango.FSE.Diagnostics.ViewModels"
xmlns:local="clr-namespace:Tango.FSE.Diagnostics.Views"
mc:Ignorable="d"
- d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
+ d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
<Grid>
- <TextBlock FontSize="60" HorizontalAlignment="Center" VerticalAlignment="Center">Diagnostics View</TextBlock>
+ <local:DiagnosticsView/>
</Grid>
</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Tango.FSE.Firmware.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Tango.FSE.Firmware.csproj
index 6df43ccce..18b8e81b4 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Tango.FSE.Firmware.csproj
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Tango.FSE.Firmware.csproj
@@ -24,6 +24,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj
index 287273015..3c740f103 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj
@@ -24,6 +24,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Tango.FSE.Upgrade.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Tango.FSE.Upgrade.csproj
index a3acc4b19..afc7344f5 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Tango.FSE.Upgrade.csproj
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Tango.FSE.Upgrade.csproj
@@ -24,6 +24,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/CacheManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/CacheManager.cs
deleted file mode 100644
index 389e17808..000000000
--- a/Software/Visual_Studio/FSE/Tango.FSE.BL/CacheManager.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using LiteDB;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Tango.FSE.BL
-{
- public class CacheManager
- {
- public String DatabasePath { get; private set; }
-
- private static CacheManager _default;
- public static CacheManager Default
- {
- get
- {
- if (_default == null)
- {
- _default = new CacheManager(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Twine", "Tango", "Cache", Path.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName) + ".cache"));
- }
-
- return _default;
- }
- }
-
- public CacheManager(String databasePath)
- {
- DatabasePath = databasePath;
- }
-
- public LiteDatabase CreateContext()
- {
- Directory.CreateDirectory(Path.GetDirectoryName(DatabasePath));
- return new LiteDatabase(DatabasePath);
- }
- }
-}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/DiskCacheManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/DiskCacheManager.cs
new file mode 100644
index 000000000..15f67c59a
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/DiskCacheManager.cs
@@ -0,0 +1,57 @@
+using LiteDB;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.BL
+{
+ /// <summary>
+ /// Represents a disk cache manager.
+ /// </summary>
+ public class DiskCacheManager
+ {
+ /// <summary>
+ /// Gets the database file path.
+ /// </summary>
+ public String DatabasePath { get; private set; }
+
+ private static DiskCacheManager _default;
+ /// <summary>
+ /// Gets the default instance.
+ /// </summary>
+ public static DiskCacheManager Default
+ {
+ get
+ {
+ if (_default == null)
+ {
+ _default = new DiskCacheManager(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Twine", "Tango", "Cache", Path.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName) + ".cache"));
+ }
+
+ return _default;
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DiskCacheManager"/> class.
+ /// </summary>
+ /// <param name="databasePath">The database path.</param>
+ public DiskCacheManager(String databasePath)
+ {
+ DatabasePath = databasePath;
+ }
+
+ /// <summary>
+ /// Creates a new disk cache context.
+ /// </summary>
+ /// <returns></returns>
+ public LiteDatabase CreateContext()
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(DatabasePath));
+ return new LiteDatabase(DatabasePath);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/EntityRepositoryBase.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/EntityRepositoryBase.cs
new file mode 100644
index 000000000..2ce9b68f1
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/EntityRepositoryBase.cs
@@ -0,0 +1,137 @@
+using ExpressionTreeToString;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Tango.BL;
+
+namespace Tango.FSE.BL
+{
+ public abstract class EntityRepositoryBase<TEntity, TCachedEntity> : FSEServiceBase where TEntity : ObservableEntity<TEntity> where TCachedEntity : ObservableEntityDTO<TCachedEntity, TEntity>
+ {
+ private MemoryCacheDictionary<String, TCachedEntity> _memoryCache;
+
+ public EntityRepositoryBase()
+ {
+ _memoryCache = MemoryCache.GetOrCreateCache<String, TCachedEntity>(typeof(TEntity).Name);
+ }
+
+ protected Task<List<TEntity>> FindAll(Expression<Func<TEntity, bool>> expression, params DataResolverNode[] nodes)
+ {
+ return DataResolver<List<TEntity>>.Builder.New()
+ .ConfigureCascade(nodes)
+ .InMemoryCache((context) =>
+ {
+ return _memoryCache
+ .ToList(true)
+ .Where(GetCacheExpression(expression).Compile())
+ .ToList()
+ .Select(x => ConvertToEntity(x))
+ .ToList();
+ })
+ .Online((context) =>
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ var entities = db.Set<TEntity>().WhereDynamic(expression.ToString()).ToList();
+
+ using (var cache = DiskCache.CreateContext())
+ {
+ var collection = cache.GetCollection<TCachedEntity>();
+
+ foreach (var entity in entities)
+ {
+ var cachedEntity = ConvertToCached(entity);
+ _memoryCache.Put(entity.Guid, cachedEntity);
+ collection.Upsert(cachedEntity);
+ }
+ }
+
+ return entities;
+ }
+ })
+ .DiskCache((context) =>
+ {
+ using (var cache = DiskCache.CreateContext())
+ {
+ List<TEntity> entities = new List<TEntity>();
+
+ var cachedEntities = cache.GetCollection<TCachedEntity>().Find(GetCacheExpression(expression)).ToList();
+
+ foreach (var cachedEntity in cachedEntities)
+ {
+ _memoryCache.Put(cachedEntity.Guid, cachedEntity);
+ entities.Add(ConvertToEntity(cachedEntity));
+ }
+
+ return entities;
+ }
+ })
+ .BuildExecuteAsync();
+ }
+
+ protected Task<TEntity> FindOne(Expression<Func<TEntity, bool>> expression, params DataResolverNode[] nodes)
+ {
+ return DataResolver<TEntity>.Builder.New()
+ .ConfigureCascade(nodes)
+ .InMemoryCache((context) =>
+ {
+ return ConvertToEntity(_memoryCache
+ .ToList(true)
+ .First(GetCacheExpression(expression).Compile()));
+ })
+ .Online((context) =>
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ var entity = db.Set<TEntity>().First(expression);
+
+ using (var cache = DiskCache.CreateContext())
+ {
+ var collection = cache.GetCollection<TCachedEntity>();
+ var cachedEntity = ConvertToCached(entity);
+ _memoryCache.Put(entity.Guid, cachedEntity);
+ collection.Upsert(cachedEntity);
+ }
+
+ return entity;
+ }
+ })
+ .DiskCache((context) =>
+ {
+ using (var cache = DiskCache.CreateContext())
+ {
+ var cachedEntity = cache.GetCollection<TCachedEntity>().FindOne(GetCacheExpression(expression));
+
+ _memoryCache.Put(cachedEntity.Guid, cachedEntity);
+
+ return ConvertToEntity(cachedEntity);
+ }
+ })
+ .BuildExecuteAsync();
+ }
+
+ protected virtual Expression<Func<TCachedEntity, bool>> GetCacheExpression(Expression<Func<TEntity, bool>> expression)
+ {
+ String str = expression.ToString("C#");
+ int startIndex = str.IndexOf("=>");
+ str = str.Substring(startIndex + 2, str.Length - (startIndex + 2));
+ str = Regex.Replace(str, @"\((.*?)\)", "");
+
+ var xparam = Expression.Parameter(typeof(TCachedEntity), expression.Parameters[0].Name);
+ Expression<Func<TCachedEntity, bool>> expr = (Expression<Func<TCachedEntity, bool>>)System.Linq.Dynamic.DynamicExpression
+ .ParseLambda(
+ new[] { xparam },
+ typeof(bool),
+ str);
+
+ return expr;
+ }
+
+ protected abstract TCachedEntity ConvertToCached(TEntity entity);
+ protected abstract TEntity ConvertToEntity(TCachedEntity cachedEntity);
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServiceBase.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServiceBase.cs
index f2eb0dbe1..1f22134d2 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServiceBase.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServiceBase.cs
@@ -30,12 +30,20 @@ namespace Tango.FSE.BL
get { return Authentication.CurrentUser; }
}
- public CacheManager DiskCache { get; set; }
+ protected DiskCacheManager DiskCache
+ {
+ get { return DiskCacheManager.Default; }
+ }
+
+ protected MemoryCacheManager MemoryCache
+ {
+ get { return MemoryCacheManager.Default; }
+ }
public FSEServiceBase()
{
TangoIOC.Default.Inject(this);
- DiskCache = CacheManager.Default;
+
TangoIOC.Default.GetInstanceWhenAvailable<FSEServicesContainer>((x) =>
{
Services = x;
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs
index 60d0fb372..1c2d5901a 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs
@@ -43,6 +43,11 @@ namespace Tango.FSE.BL
public TangoVersionsService TangoVersionsService { get; set; }
/// <summary>
+ /// Gets or sets the tango versions service.
+ /// </summary>
+ public TechComponentsService TechComponentsService { get; set; }
+
+ /// <summary>
/// Initializes a new instance of the <see cref="FSEServicesContainer"/> class.
/// </summary>
/// <param name="authentication">The authentication.</param>
@@ -54,6 +59,7 @@ namespace Tango.FSE.BL
AuthenticationService = new AuthenticationService();
BugReportingService = new BugReportingService();
TangoVersionsService = new TangoVersionsService();
+ TechComponentsService = new TechComponentsService();
}
}
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/IMemoryCacheDictionary.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/IMemoryCacheDictionary.cs
new file mode 100644
index 000000000..3b64b4676
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/IMemoryCacheDictionary.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.BL
+{
+ /// <summary>
+ /// Represents an in-memory cache dictionary.
+ /// </summary>
+ public interface IMemoryCacheDictionary
+ {
+ /// <summary>
+ /// Gets the cache name.
+ /// </summary>
+ String Name { get; }
+
+ /// <summary>
+ /// Gets the count of items.
+ /// </summary>
+ int Count { get; }
+
+ /// <summary>
+ /// Clears this all items from cache.
+ /// </summary>
+ void Clear();
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/MemoryCacheDictionary.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/MemoryCacheDictionary.cs
new file mode 100644
index 000000000..8d7a563ff
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/MemoryCacheDictionary.cs
@@ -0,0 +1,218 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.BL
+{
+ /// <summary>
+ /// Represents an in-memory cache dictionary of type T.
+ /// </summary>
+ /// <typeparam name="TValue"></typeparam>
+ /// <seealso cref="Tango.FSE.BL.IMemoryCacheDictionary" />
+ public class MemoryCacheDictionary<TKey, TValue> : IMemoryCacheDictionary where TValue : class
+ {
+ private ConcurrentDictionary<TKey, TValue> _dictionary;
+
+ /// <summary>
+ /// Gets the cache name.
+ /// </summary>
+ public String Name { get; private set; }
+
+ /// <summary>
+ /// Gets the count of items.
+ /// </summary>
+ public int Count
+ {
+ get { return _dictionary.Count; }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MemoryCacheDictionary{T}"/> class.
+ /// </summary>
+ /// <param name="name">The name of the cache.</param>
+ public MemoryCacheDictionary(String name)
+ {
+ Name = name;
+ _dictionary = new ConcurrentDictionary<TKey, TValue>();
+ }
+
+ /// <summary>
+ /// Determines whether this cache contains an element with the specified key.
+ /// </summary>
+ /// <param name="key">The key.</param>
+ public bool ContainsKey(TKey key)
+ {
+ return _dictionary.ContainsKey(key);
+ }
+
+ /// <summary>
+ /// Gets a cached item by the specified key.
+ /// </summary>
+ /// <param name="key">The key.</param>
+ /// <param name="throwIfNotFound">if set to <c>true</c> throws exception when item not found otherwise returns null.</param>
+ /// <exception cref="KeyNotFoundException"></exception>
+ public TValue Get(TKey key, bool throwIfNotFound = true)
+ {
+ TValue value = null;
+
+ if (_dictionary.TryGetValue(key, out value))
+ {
+ return value;
+ }
+ else
+ {
+ if (throwIfNotFound)
+ {
+ throw new KeyNotFoundException($"Could not locate key '{key}' on cache '{Name}'.");
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Puts a new cached item or overrides an existing one.
+ /// </summary>
+ /// <param name="key">The key.</param>
+ /// <param name="value">The value.</param>
+ public void Put(TKey key, TValue value)
+ {
+ _dictionary[key] = value;
+ }
+
+ /// <summary>
+ /// Get all cached items as a list.
+ /// </summary>
+ /// <returns></returns>
+ public List<TValue> ToList(bool throwOnEmpty = false)
+ {
+ var list = _dictionary.Select(x => x.Value).ToList();
+
+ if (throwOnEmpty && list.Count == 0)
+ {
+ throw new KeyNotFoundException("The memory cache does not contain any items.");
+ }
+
+ return list;
+ }
+
+ /// <summary>
+ /// Clears this all items from cache.
+ /// </summary>
+ public void Clear()
+ {
+ _dictionary.Clear();
+ }
+ }
+
+ /// <summary>
+ /// Represents an in-memory cache dictionary of type T.
+ /// </summary>
+ /// <typeparam name="TValue"></typeparam>
+ /// <seealso cref="Tango.FSE.BL.IMemoryCacheDictionary" />
+ public class MemoryCacheDoubleKeyDictionary<TKey1, TKey2, TValue> : IMemoryCacheDictionary where TValue : class
+ {
+ private ConcurrentDictionary<String, TValue> _dictionary;
+
+ /// <summary>
+ /// Gets the cache name.
+ /// </summary>
+ public String Name { get; private set; }
+
+ /// <summary>
+ /// Gets the count of items.
+ /// </summary>
+ public int Count
+ {
+ get { return _dictionary.Count; }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MemoryCacheDictionary{T}"/> class.
+ /// </summary>
+ /// <param name="name">The name of the cache.</param>
+ public MemoryCacheDoubleKeyDictionary(String name)
+ {
+ Name = name;
+ _dictionary = new ConcurrentDictionary<String, TValue>();
+ }
+
+ /// <summary>
+ /// Determines whether this cache contains an element with the specified keys.
+ /// </summary>
+ /// <param name="key1">The first key.</param>
+ /// <param name="key2">The second key.</param>
+ public bool ContainsKey(TKey1 key1, TKey2 key2)
+ {
+ return _dictionary.ContainsKey(key1.ToString() + key2.ToString());
+ }
+
+ /// <summary>
+ /// Gets a cached item by the specified keys.
+ /// </summary>
+ /// <param name="key1">The first key.</param>
+ /// <param name="key2">The second key.</param>
+ /// <param name="throwIfNotFound">if set to <c>true</c> throws exception when item not found otherwise returns null.</param>
+ /// <exception cref="KeyNotFoundException"></exception>
+ public TValue Get(TKey1 key1, TKey2 key2, bool throwIfNotFound = true)
+ {
+ TValue value = null;
+
+ if (_dictionary.TryGetValue(key1.ToString() + key2.ToString(), out value))
+ {
+ return value;
+ }
+ else
+ {
+ if (throwIfNotFound)
+ {
+ throw new KeyNotFoundException($"Could not locate key '{key1 + " " + key2}' on cache '{Name}'.");
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Puts a new cached item or overrides an existing one.
+ /// </summary>
+ /// <param name="key1">The first key.</param>
+ /// <param name="key2">The second key.</param>
+ /// <param name="value">The value.</param>
+ public void Put(TKey1 key1, TKey2 key2, TValue value)
+ {
+ _dictionary[key1.ToString() + key2.ToString()] = value;
+ }
+
+ /// <summary>
+ /// Get all cached items as a list.
+ /// </summary>
+ /// <returns></returns>
+ public List<TValue> ToList(bool throwOnEmpty = false)
+ {
+ var list = _dictionary.Select(x => x.Value).ToList();
+
+ if (throwOnEmpty && list.Count == 0)
+ {
+ throw new KeyNotFoundException("The memory cache does not contain any items.");
+ }
+
+ return list;
+ }
+
+ /// <summary>
+ /// Clears this all items from cache.
+ /// </summary>
+ public void Clear()
+ {
+ _dictionary.Clear();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/MemoryCacheManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/MemoryCacheManager.cs
new file mode 100644
index 000000000..6a53e302f
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/MemoryCacheManager.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.BL
+{
+ /// <summary>
+ /// Represents an in-memory global cache manager.
+ /// </summary>
+ public class MemoryCacheManager
+ {
+ private Dictionary<String, IMemoryCacheDictionary> _cacheDictionaries;
+
+ private static MemoryCacheManager _instance;
+ /// <summary>
+ /// Gets the default singleton instance.
+ /// </summary>
+ public static MemoryCacheManager Default
+ {
+ get
+ {
+ if (_instance == null)
+ {
+ _instance = new MemoryCacheManager();
+ }
+
+ return _instance;
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MemoryCacheManager"/> class.
+ /// </summary>
+ public MemoryCacheManager()
+ {
+ _cacheDictionaries = new Dictionary<String, IMemoryCacheDictionary>();
+ }
+
+ /// <summary>
+ /// Gets the specified <see cref="MemoryCacheDictionary{T}"/> or creates and return a new one.
+ /// </summary>
+ /// <typeparam name="TValue"></typeparam>
+ /// <param name="name">The name.</param>
+ /// <returns></returns>
+ public MemoryCacheDictionary<TKey, TValue> GetOrCreateCache<TKey, TValue>(String name) where TValue : class
+ {
+ if (_cacheDictionaries.ContainsKey(name))
+ {
+ return _cacheDictionaries[name] as MemoryCacheDictionary<TKey, TValue>;
+ }
+ else
+ {
+ var cacheDictionary = new MemoryCacheDictionary<TKey, TValue>(name);
+ _cacheDictionaries[name] = cacheDictionary;
+ return cacheDictionary;
+ }
+ }
+
+ /// <summary>
+ /// Gets the specified <see cref="MemoryCacheDoubleKeyDictionary{T}"/> or creates and return a new one.
+ /// </summary>
+ /// <typeparam name="TValue"></typeparam>
+ /// <param name="name">The name.</param>
+ /// <returns></returns>
+ public MemoryCacheDoubleKeyDictionary<TKey1, TKey2, TValue> GetOrCreateCache<TKey1, TKey2, TValue>(String name) where TValue : class
+ {
+ if (_cacheDictionaries.ContainsKey(name))
+ {
+ return _cacheDictionaries[name] as MemoryCacheDoubleKeyDictionary<TKey1, TKey2, TValue>;
+ }
+ else
+ {
+ var cacheDictionary = new MemoryCacheDoubleKeyDictionary<TKey1, TKey2, TValue>(name);
+ _cacheDictionaries[name] = cacheDictionary;
+ return cacheDictionary;
+ }
+ }
+
+ /// <summary>
+ /// Clears all <see cref="IMemoryCacheDictionary"/> stored by this manager.
+ /// </summary>
+ public void ClearAll()
+ {
+ foreach (var cacheDictionary in _cacheDictionaries)
+ {
+ cacheDictionary.Value.Clear();
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/ReadOnlyEntityRepository.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/ReadOnlyEntityRepository.cs
new file mode 100644
index 000000000..45fb65e10
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/ReadOnlyEntityRepository.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using Tango.BL;
+
+namespace Tango.FSE.BL
+{
+ public class ReadOnlyEntityRepository<TEntity, TCachedEntity> : EntityRepositoryBase<TEntity, TCachedEntity> where TEntity : ObservableEntity<TEntity> where TCachedEntity : ObservableEntityDTO<TCachedEntity, TEntity>
+ {
+ private Func<TCachedEntity, TEntity> _convertToEntity;
+ private Func<TEntity, TCachedEntity> _convertToCached;
+ private DataResolverNode[] _nodes;
+
+ public ReadOnlyEntityRepository(Func<TCachedEntity, TEntity> convertToEntity, Func<TEntity, TCachedEntity> convertToCached, params DataResolverNode[] nodes)
+ {
+ _convertToEntity = convertToEntity;
+ _convertToCached = convertToCached;
+ _nodes = nodes;
+ }
+
+ protected override TCachedEntity ConvertToCached(TEntity entity)
+ {
+ return _convertToCached.Invoke(entity);
+ }
+
+ protected override TEntity ConvertToEntity(TCachedEntity cachedEntity)
+ {
+ return _convertToEntity(cachedEntity);
+ }
+
+ public Task<List<TEntity>> FindAll(Expression<Func<TEntity, bool>> expression)
+ {
+ return FindAll(expression, _nodes);
+ }
+
+ public Task<TEntity> FindOne(Expression<Func<TEntity, bool>> expression)
+ {
+ return FindOne(expression, _nodes);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/MachinesService.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/MachinesService.cs
index 03d17e5ed..34aaf86b6 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/MachinesService.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/MachinesService.cs
@@ -26,16 +26,16 @@ namespace Tango.FSE.BL.Services
private const string FULL_MACHINES_COLLECTION = "Machines_Full";
private bool _fullMachinesCachePerformed;
- private ConcurrentDictionary<String, CachedMachine> _machinesCache;
- private ConcurrentDictionary<String, CachedMachine> _machinesCacheFull;
+ private MemoryCacheDictionary<String, CachedMachine> _machinesCache;
+ private MemoryCacheDictionary<String, CachedMachine> _machinesCacheFull;
/// <summary>
/// Initializes a new instance of the <see cref="MachinesService"/> class.
/// </summary>
public MachinesService()
{
- _machinesCache = new ConcurrentDictionary<string, CachedMachine>();
- _machinesCacheFull = new ConcurrentDictionary<string, CachedMachine>();
+ _machinesCache = MemoryCache.GetOrCreateCache<String, CachedMachine>(MACHINES_COLLECTION);
+ _machinesCacheFull = MemoryCache.GetOrCreateCache<String, CachedMachine>(FULL_MACHINES_COLLECTION);
}
/// <summary>
@@ -53,7 +53,7 @@ namespace Tango.FSE.BL.Services
.ConfigureCascade(DataResolverNode.InMemoryCache, DataResolverNode.Online, DataResolverNode.DiskCache)
.InMemoryCache((context) =>
{
- return _machinesCache[serialNumber].ToObservable();
+ return _machinesCache.Get(serialNumber).ToObservable();
})
.Online((context) =>
{
@@ -72,7 +72,7 @@ namespace Tango.FSE.BL.Services
var m = cachedMachine.ToObservable();
//Store in memory cache.
- _machinesCache[serialNumber] = cachedMachine;
+ _machinesCache.Put(serialNumber, cachedMachine);
//Store disk cache.
try
@@ -98,6 +98,10 @@ namespace Tango.FSE.BL.Services
using (var cache = DiskCache.CreateContext())
{
var cachedMachine = cache.GetCollection<CachedMachine>(MACHINES_COLLECTION).FindOne(x => x.SerialNumber == serialNumber && x.OrganizationGuid == CurrentUser.OrganizationGuid);
+
+ //Store in memory cache.
+ _machinesCache.Put(serialNumber, cachedMachine);
+
return cachedMachine.ToObservable();
}
})
@@ -126,7 +130,7 @@ namespace Tango.FSE.BL.Services
.ConfigureCascade(DataResolverNode.InMemoryCache, DataResolverNode.Online, DataResolverNode.DiskCache)
.InMemoryCache((context) =>
{
- return _machinesCacheFull[serialNumber].ToObservable();
+ return _machinesCacheFull.Get(serialNumber).ToObservable();
})
.Online((context) =>
{
@@ -147,7 +151,7 @@ namespace Tango.FSE.BL.Services
var cachedMachine = CachedMachine.FromObservable<CachedMachine>(machine);
//Store in memory cache.
- _machinesCacheFull[serialNumber] = cachedMachine;
+ _machinesCacheFull.Put(serialNumber, cachedMachine);
//Store disk cache.
try
@@ -208,6 +212,10 @@ namespace Tango.FSE.BL.Services
using (var cache = DiskCache.CreateContext())
{
var cachedMachine = cache.GetCollection<CachedMachine>(FULL_MACHINES_COLLECTION).FindOne(x => x.SerialNumber == serialNumber && x.OrganizationGuid == CurrentUser.OrganizationGuid);
+
+ //Store in memory cache.
+ _machinesCacheFull.Put(serialNumber, cachedMachine);
+
return cachedMachine.ToObservable();
}
})
@@ -228,7 +236,6 @@ namespace Tango.FSE.BL.Services
{
var machines = _machinesCache
.ToList()
- .Select(x => x.Value)
.Where(x => x.OrganizationGuid == CurrentUser.OrganizationGuid)
.Select(x => x.ToObservable())
.ToList();
@@ -256,7 +263,7 @@ namespace Tango.FSE.BL.Services
{
var cachedMachine = CachedMachine.FromObservable<CachedMachine>(machine);
- _machinesCache[machine.SerialNumber] = cachedMachine;
+ _machinesCache.Put(machine.SerialNumber, cachedMachine);
collection.Upsert(cachedMachine);
}
@@ -282,7 +289,7 @@ namespace Tango.FSE.BL.Services
foreach (var cachedMachine in cachedMachines)
{
- _machinesCache[cachedMachine.SerialNumber] = cachedMachine;
+ _machinesCache.Put(cachedMachine.SerialNumber, cachedMachine);
}
return cachedMachines.Select(x => x.ToObservable()).ToList();
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/TangoVersionsService.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/TangoVersionsService.cs
index 2c44cac74..94387004d 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/TangoVersionsService.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/TangoVersionsService.cs
@@ -15,11 +15,11 @@ namespace Tango.FSE.BL.Services
public class TangoVersionsService : FSEServiceBase
{
private const string TANGO_VERSIONS_COLLECTION = "TangoVersions";
- private ConcurrentDictionary<String, CachedTangoVersion> _tangoVersionsCache;
+ private MemoryCacheDoubleKeyDictionary<String, String, CachedTangoVersion> _tangoVersionsCache;
public TangoVersionsService()
{
- _tangoVersionsCache = new ConcurrentDictionary<string, CachedTangoVersion>();
+ _tangoVersionsCache = MemoryCache.GetOrCreateCache<String, String, CachedTangoVersion>(TANGO_VERSIONS_COLLECTION);
}
/// <summary>
@@ -34,7 +34,6 @@ namespace Tango.FSE.BL.Services
{
var tangoVersions = _tangoVersionsCache
.ToList()
- .Select(x => x.Value)
.Where(x => x.EnvironmentID == Authentication.CurrentEnvironment.ID)
.Select(x => x.TangoVersion.ToObservable())
.OrderByDescending(x => Version.Parse(x.Version))
@@ -66,7 +65,7 @@ namespace Tango.FSE.BL.Services
cachedTangoVersion.EnvironmentID = Authentication.CurrentEnvironment.ID;
cachedTangoVersion.TangoVersion = tangoVersionDTO;
- _tangoVersionsCache[tangoVersion.Version + " " + Authentication.CurrentEnvironment.ID] = cachedTangoVersion;
+ _tangoVersionsCache.Put(tangoVersion.Version, Authentication.CurrentEnvironment.ID, cachedTangoVersion);
collection.Upsert(cachedTangoVersion);
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/TechComponentsService.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/TechComponentsService.cs
new file mode 100644
index 000000000..f0f72be7a
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/TechComponentsService.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL;
+using Tango.BL.DTO;
+using Tango.BL.Entities;
+
+namespace Tango.FSE.BL.Services
+{
+ public class TechComponentsService : FSEServiceBase
+ {
+ public ReadOnlyEntityRepository<TechMonitor, TechMonitorDTO> Monitors { get; private set; }
+ public ReadOnlyEntityRepository<TechIo, TechIoDTO> IOs { get; private set; }
+ public ReadOnlyEntityRepository<TechDispenser, TechDispenserDTO> Dispensers { get; private set; }
+
+ public TechComponentsService()
+ {
+ Monitors = new ReadOnlyEntityRepository<TechMonitor, TechMonitorDTO>(
+ x => x.ToObservable(),
+ x => TechMonitorDTO.FromObservable(x),
+ DataResolverNode.InMemoryCache,
+ DataResolverNode.Online,
+ DataResolverNode.DiskCache);
+
+ IOs = new ReadOnlyEntityRepository<TechIo, TechIoDTO>(
+ x => x.ToObservable(),
+ x => TechIoDTO.FromObservable(x),
+ DataResolverNode.InMemoryCache,
+ DataResolverNode.Online,
+ DataResolverNode.DiskCache);
+
+ Dispensers = new ReadOnlyEntityRepository<TechDispenser, TechDispenserDTO>(
+ x => x.ToObservable(),
+ x => TechDispenserDTO.FromObservable(x),
+ DataResolverNode.InMemoryCache,
+ DataResolverNode.Online,
+ DataResolverNode.DiskCache);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj b/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj
index ad514c09c..f0097c2f6 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj
@@ -38,6 +38,9 @@
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
</Reference>
+ <Reference Include="ExpressionTreeToString, Version=2.0.20.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\ExpressionTreeToString.2.0.20\lib\netstandard2.0\ExpressionTreeToString.dll</HintPath>
+ </Reference>
<Reference Include="LiteDB, Version=5.0.4.0, Culture=neutral, PublicKeyToken=4ee40123013c9f27, processorArchitecture=MSIL">
<HintPath>..\..\packages\LiteDB.5.0.4\lib\net45\LiteDB.dll</HintPath>
</Reference>
@@ -50,6 +53,9 @@
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
+ <Reference Include="System.Linq.Dynamic, Version=1.0.6132.35681, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\System.Linq.Dynamic.1.0.7\lib\net40\System.Linq.Dynamic.dll</HintPath>
+ </Reference>
<Reference Include="System.Runtime" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Xaml" />
@@ -69,15 +75,20 @@
<Reference Include="Z.Expressions.Eval, Version=3.1.8.0, Culture=neutral, PublicKeyToken=59b66d028979105b, processorArchitecture=MSIL">
<HintPath>..\..\packages\Z.Expressions.Eval.3.1.8\lib\net45\Z.Expressions.Eval.dll</HintPath>
</Reference>
+ <Reference Include="ZSpitz.Util, Version=0.0.6.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\ZSpitz.Util.0.0.6\lib\netstandard2.0\ZSpitz.Util.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
+ <Compile Include="EntityRepositoryBase.cs" />
+ <Compile Include="MemoryCacheDictionary.cs" />
<Compile Include="CacheEntities\CachedBugInfoResponse.cs" />
<Compile Include="CacheEntities\CachedConfiguration.cs" />
<Compile Include="CacheEntities\CachedLoginResponse.cs" />
<Compile Include="CacheEntities\CachedMachine.cs" />
<Compile Include="CacheEntities\CachedTangoVersion.cs" />
<Compile Include="CacheEntities\CachedUser.cs" />
- <Compile Include="CacheManager.cs" />
+ <Compile Include="DiskCacheManager.cs" />
<Compile Include="Connectivity\DefaultConnectivityProvider.cs" />
<Compile Include="Connectivity\IConnectivityProvider.cs" />
<Compile Include="DataResolver.cs" />
@@ -86,13 +97,17 @@
<Compile Include="FSEServiceBase.cs" />
<Compile Include="Gateway\GatewayClient.cs" />
<Compile Include="IAuthenticationService.cs" />
+ <Compile Include="IMemoryCacheDictionary.cs" />
<Compile Include="InternetConnectionException.cs" />
+ <Compile Include="MemoryCacheManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ReadOnlyEntityRepository.cs" />
<Compile Include="Services\AuthenticationService.cs" />
<Compile Include="Services\BugReportingService.cs" />
<Compile Include="Services\GatewayService.cs" />
<Compile Include="Services\MachinesService.cs" />
<Compile Include="Services\TangoVersionsService.cs" />
+ <Compile Include="Services\TechComponentsService.cs" />
<Compile Include="Services\UsersService.cs" />
<Compile Include="Web\FSEWebClient.cs" />
<Compile Include="Web\FSEWebClientBase.cs" />
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/packages.config b/Software/Visual_Studio/FSE/Tango.FSE.BL/packages.config
index 9e8400eb2..ea481ad19 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.BL/packages.config
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/packages.config
@@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework" version="6.2.0" targetFramework="net461" />
+ <package id="ExpressionTreeToString" version="2.0.20" targetFramework="net461" />
<package id="LiteDB" version="5.0.4" targetFramework="net461" />
+ <package id="Microsoft.CSharp" version="4.7.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net461" />
+ <package id="System.Linq.Dynamic" version="1.0.7" targetFramework="net461" />
<package id="Z.EntityFramework.Extensions" version="4.0.58" targetFramework="net461" />
<package id="Z.EntityFramework.Plus.EF6" version="1.12.19" targetFramework="net461" />
<package id="Z.Expressions.Eval" version="3.1.8" targetFramework="net461" />
+ <package id="ZSpitz.Util" version="0.0.6" targetFramework="net461" />
</packages> \ No newline at end of file
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Diagnostics/DiagnosticsFrame.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Diagnostics/DiagnosticsFrame.cs
index ff2364e0a..88139d628 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Diagnostics/DiagnosticsFrame.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Diagnostics/DiagnosticsFrame.cs
@@ -9,6 +9,24 @@ namespace Tango.FSE.Common.Diagnostics
{
public class DiagnosticsFrame
{
- public StartDiagnosticsResponse Diagnostics { get; set; }
+ /// <summary>
+ /// Diagnostics frame data.
+ /// </summary>
+ public StartDiagnosticsResponse Data { get; set; }
+
+ /// <summary>
+ /// The calculated local date and time by the first diagnostics response and elapsed Milli.
+ /// </summary>
+ public DateTime DiagnosticsTime { get; set; }
+
+ /// <summary>
+ /// The reported elapsed time from the previous diagnostics frame (reported by the embedded device).
+ /// </summary>
+ public TimeSpan Delta { get; set; }
+
+ /// <summary>
+ /// The average interval of diagnostics frame rate reported by the embedded device.
+ /// </summary>
+ public uint Interval { get; set; }
}
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Diagnostics/DefaultDiagnosticsProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Diagnostics/DefaultDiagnosticsProvider.cs
index eba89b198..cf49286a4 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Diagnostics/DefaultDiagnosticsProvider.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Diagnostics/DefaultDiagnosticsProvider.cs
@@ -22,6 +22,7 @@ namespace Tango.FSE.UI.Diagnostics
{
private ProducerConsumerQueue<StartDiagnosticsResponse> _diagnosticsQueue;
private Thread _queueThread;
+ private IMachineProvider _machineProvider;
#region Events
@@ -59,6 +60,7 @@ namespace Tango.FSE.UI.Diagnostics
/// <param name="machineProvider">The machine provider.</param>
public DefaultDiagnosticsProvider(IMachineProvider machineProvider)
{
+ _machineProvider = machineProvider;
_diagnosticsQueue = new ProducerConsumerQueue<StartDiagnosticsResponse>();
ThrottlingMode = SettingsManager.Default.GetOrCreate<FSESettings>().DiagnosticsThrottlingMode;
machineProvider.MachineOperator.DiagnosticsDataAvailable += MachineOperator_DiagnosticsDataAvailable;
@@ -95,15 +97,24 @@ namespace Tango.FSE.UI.Diagnostics
}
}
- private void PostDiagnostics(StartDiagnosticsResponse diagnostics)
+ private void PostDiagnostics(StartDiagnosticsResponse data)
{
- FrameRate = (int)diagnostics.ElapsedMilli;
+ if (data.Monitors == null || _machineProvider.MachineOperator.DeviceInformation == null) return;
+
+ FrameRate = (int)data.ElapsedMilli;
+
+ uint interval = _machineProvider.MachineOperator.DeviceInformation.DiagnosticsInterval;
+ DateTime diagnosticsTime = DateTime.ParseExact(data.DateTime, "MM/dd/yyyy HH:mm:ss.fff", null);
+ TimeSpan delta = TimeSpan.FromMilliseconds(data.ElapsedMilli);
FrameReceived?.Invoke(this, new DiagnosticsFrameReceivedEventArgs()
{
Frame = new DiagnosticsFrame()
{
- Diagnostics = diagnostics,
+ Data = data,
+ DiagnosticsTime = diagnosticsTime,
+ Delta = delta,
+ Interval = interval
},
});
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs
index 15ae3af50..a9a677368 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs
@@ -6,6 +6,8 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.BL;
+using Tango.BL.DTO;
+using Tango.BL.Entities;
using Tango.Core.Commands;
using Tango.Core.Cryptography;
using Tango.FSE.Common;
diff --git a/Software/Visual_Studio/Tango.Scripting/ExpressionGenerator.cs b/Software/Visual_Studio/Tango.Scripting/ExpressionGenerator.cs
new file mode 100644
index 000000000..8db917a10
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Scripting/ExpressionGenerator.cs
@@ -0,0 +1,22 @@
+using Microsoft.CodeAnalysis.CSharp.Scripting;
+using Microsoft.CodeAnalysis.Scripting;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Scripting
+{
+ public static class ExpressionGenerator
+ {
+ public static Func<T, bool> GenerateExpression<T>(String body, params Assembly[] assemblies)
+ {
+ var options = ScriptOptions.Default.AddReferences(assemblies);
+ Func<T, bool> func = CSharpScript.EvaluateAsync<Func<T, bool>>(body, options).Result;
+ return func;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Scripting/Tango.Scripting.csproj b/Software/Visual_Studio/Tango.Scripting/Tango.Scripting.csproj
index f8dbc66c0..718bd96ce 100644
--- a/Software/Visual_Studio/Tango.Scripting/Tango.Scripting.csproj
+++ b/Software/Visual_Studio/Tango.Scripting/Tango.Scripting.csproj
@@ -141,6 +141,7 @@
<Link>GlobalVersionInfo.cs</Link>
</Compile>
<Compile Include="CompilerError.cs" />
+ <Compile Include="ExpressionGenerator.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ScriptEngine.cs" />
<Compile Include="OnExecuteParameters.cs" />
@@ -175,7 +176,7 @@
<Import Project="..\packages\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets" Condition="Exists('..\packages\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets')" />
<ProjectExtensions>
<VisualStudio>
- <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" />
+ <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" />
</VisualStudio>
</ProjectExtensions>
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.WebRTC/WebRtcTransportAdapter.cs b/Software/Visual_Studio/Tango.WebRTC/WebRtcTransportAdapter.cs
index d0bfc886d..69d9fb6ae 100644
--- a/Software/Visual_Studio/Tango.WebRTC/WebRtcTransportAdapter.cs
+++ b/Software/Visual_Studio/Tango.WebRTC/WebRtcTransportAdapter.cs
@@ -143,19 +143,31 @@ namespace Tango.WebRTC
else
{
LogManager.Log("Waiting for offer...");
- completed = true;
State = TransportComponentState.Connected;
- completionSource.SetResult(true);
+
+ if (!completed)
+ {
+ completed = true;
+ completionSource.SetResult(true);
+ }
}
}
catch (Exception ex)
{
- completionSource.SetException(ex);
+ if (!completed)
+ {
+ completed = true;
+ completionSource.SetException(ex);
+ }
}
}
else
{
- completionSource.SetResult(true);
+ if (!completed)
+ {
+ completed = true;
+ completionSource.SetResult(true);
+ }
}
});