aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio
diff options
context:
space:
mode:
authorRoy Ben Shabat <Roy.mail.net@gmail.com>2025-08-04 01:09:55 +0300
committerRoy Ben Shabat <Roy.mail.net@gmail.com>2025-08-04 01:09:55 +0300
commit8bbeffb422e8535c399f1eb76a55fdee5a1c65b6 (patch)
treef200faa0e11c23f9105c3f12e0a6a2ea51832214 /Software/Visual_Studio
parent0df9f37075dd697ac34f4ed2a2749f62aa27a654 (diff)
downloadTango-8bbeffb422e8535c399f1eb76a55fdee5a1c65b6.tar.gz
Tango-8bbeffb422e8535c399f1eb76a55fdee5a1c65b6.zip
Telemetry JobRuns.
Diffstat (limited to 'Software/Visual_Studio')
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs2
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/Destinations/TelemetryAzureHubDestination.cs10
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/ExtensionMethods/ITelemetryExtensions.cs6
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/ITelemetryHistorySource.cs37
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/ITelemetrySource.cs17
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/ITelemetryStreamingSource.cs23
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/Mappers/JobRunMapper.cs320
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryDiagnosticsSource.cs14
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobRunsHistorySource.cs29
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobRunsStreamingSource.cs63
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/Tango.Telemetry.csproj8
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryDiagnosticsFrame.cs2
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryJobRun.cs103
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/TelemetryAvailableEventArgs.cs7
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/TelemetryHistorySourceDirection.cs20
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/TelemetryLiteDBStorageManager.cs13
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/TelemetryNameAttribute.cs5
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/TelemetryPublishPackage.cs3
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/TelemetryPublisher.cs44
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/TelemetryPublisherConfiguration.cs22
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/TelemetryStreamingAvailableEventArgs.cs13
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/app.config59
-rw-r--r--Software/Visual_Studio/Tango.Telemetry/packages.config1
-rw-r--r--Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/App.config16
-rw-r--r--Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Program.cs50
-rw-r--r--Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Tango.Telemetry.Tester.IOT.CLI.csproj11
-rw-r--r--Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/packages.config1
27 files changed, 733 insertions, 166 deletions
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs
index 8a29b2f8b..3ed415e3f 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs
@@ -310,7 +310,7 @@ namespace Tango.PPC.MachineSettings.ViewModels
public bool PowerOffTimeVisible
{
- get { return SelectedIdleTime.Minutes != Common.PowerSavingModes.Never; }
+ get { return SelectedIdleTime?.Minutes != Common.PowerSavingModes.Never; }
}
public ColorConversionSettings ColorConversionSettings { get; set; }
diff --git a/Software/Visual_Studio/Tango.Telemetry/Destinations/TelemetryAzureHubDestination.cs b/Software/Visual_Studio/Tango.Telemetry/Destinations/TelemetryAzureHubDestination.cs
index 01ad31432..94e949ba3 100644
--- a/Software/Visual_Studio/Tango.Telemetry/Destinations/TelemetryAzureHubDestination.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/Destinations/TelemetryAzureHubDestination.cs
@@ -26,8 +26,12 @@ namespace Tango.Telemetry.Destinations
public String Environment { get; set; }
public String MachineType { get; set; }
public String SerialNumber { get; set; }
+ public String Organization { get; set; }
+ public String Site { get; set; }
public ITelemetry Telemetry { get; set; }
public DateTime UploadTime { get; set; }
+ public DateTime CreatedTime { get; set; }
+ public int Version { get; set; }
public String ToPayload()
{
@@ -122,10 +126,14 @@ namespace Tango.Telemetry.Destinations
ADXPAckage adxPackage = new ADXPAckage();
adxPackage.Type = package.TelemetryName;
+ adxPackage.Version = package.TelemetryVersion;
adxPackage.Environment = package.Environment;
adxPackage.MachineType = package.MachineType;
adxPackage.SerialNumber = package.SerialNumber;
- adxPackage.UploadTime = DateTime.UtcNow;
+ adxPackage.Organization = package.Organization;
+ adxPackage.Site = package.Site;
+ adxPackage.UploadTime = DateTime.UtcNow;
+ adxPackage.CreatedTime = package.PendingTelemetry.TelemetryObject.Time;
adxPackage.Telemetry = package.PendingTelemetry.TelemetryObject;
var message = new Message(Encoding.UTF8.GetBytes(adxPackage.ToPayload()))
diff --git a/Software/Visual_Studio/Tango.Telemetry/ExtensionMethods/ITelemetryExtensions.cs b/Software/Visual_Studio/Tango.Telemetry/ExtensionMethods/ITelemetryExtensions.cs
index ba016ed72..370e185ab 100644
--- a/Software/Visual_Studio/Tango.Telemetry/ExtensionMethods/ITelemetryExtensions.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/ExtensionMethods/ITelemetryExtensions.cs
@@ -12,4 +12,10 @@ public static class ITelemetryObjectExtensions
var att = obj.GetType().GetCustomAttributes(typeof(TelemetryNameAttribute), false).Cast<TelemetryNameAttribute>().FirstOrDefault();
return att?.Name ?? obj.GetType().Name;
}
+
+ public static int ToTelemetryVersion(this ITelemetry obj)
+ {
+ var att = obj.GetType().GetCustomAttributes(typeof(TelemetryNameAttribute), false).Cast<TelemetryNameAttribute>().FirstOrDefault();
+ return att?.Version ?? 1;
+ }
}
diff --git a/Software/Visual_Studio/Tango.Telemetry/ITelemetryHistorySource.cs b/Software/Visual_Studio/Tango.Telemetry/ITelemetryHistorySource.cs
index 0b118d85c..51a2e0e3e 100644
--- a/Software/Visual_Studio/Tango.Telemetry/ITelemetryHistorySource.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/ITelemetryHistorySource.cs
@@ -1,14 +1,47 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using System.Threading.Tasks;
namespace Tango.Telemetry
{
+ /// <summary>
+ /// Represents a telemetry source that provides historical telemetry data.
+ /// </summary>
public interface ITelemetryHistorySource : ITelemetrySource
{
+ /// <summary>
+ /// Gets the direction in which historical telemetry data should be published — either from oldest to newest, or vice versa.
+ ///
+ /// When the direction is set to <see cref="TelemetryHistorySourceDirection.Descending"/>,
+ /// only past data will be published. New data will not be published unless streamed from another source.
+ ///
+ /// When an <see cref="ITelemetryPublisher"/> calls <see cref="ITelemetryHistorySource.CanRequestHistory(DateTime)"/> or
+ /// <see cref="ITelemetryHistorySource.RequestHistory(DateTime)"/> for the first time and no checkpoints have been saved:
+ /// <list type="bullet">
+ /// <item><see cref="DateTime.MinValue"/> will be used if the direction is <see cref="TelemetryHistorySourceDirection.Ascending"/>.</item>
+ /// <item><see cref="DateTime.MaxValue"/> will be used if the direction is <see cref="TelemetryHistorySourceDirection.Descending"/>.</item>
+ /// </list>
+ /// </summary>
+ TelemetryHistorySourceDirection Direction { get; }
+
+ /// <summary>
+ /// Determines whether historical telemetry data can be requested starting from the specified timestamp.
+ /// </summary>
+ /// <param name="from">The start time for the historical data request.</param>
+ /// <returns>
+ /// A task that represents the asynchronous operation.
+ /// The task result contains true if history can be requested from the given time; otherwise, false.
+ /// </returns>
Task<bool> CanRequestHistory(DateTime from);
+
+ /// <summary>
+ /// Requests historical telemetry data starting from the specified timestamp.
+ /// </summary>
+ /// <param name="from">The start time for the telemetry history request.</param>
+ /// <returns>
+ /// A task that represents the asynchronous operation.
+ /// The task result contains a collection of historical telemetry records.
+ /// </returns>
Task<IEnumerable<ITelemetry>> RequestHistory(DateTime from);
}
}
diff --git a/Software/Visual_Studio/Tango.Telemetry/ITelemetrySource.cs b/Software/Visual_Studio/Tango.Telemetry/ITelemetrySource.cs
index 739c6514b..d80c6d73a 100644
--- a/Software/Visual_Studio/Tango.Telemetry/ITelemetrySource.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/ITelemetrySource.cs
@@ -1,14 +1,21 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace Tango.Telemetry
{
+ /// <summary>
+ /// Represents a telemetry source that provides telemetry data to the system.
+ /// </summary>
public interface ITelemetrySource : IDisposable
{
- String Name { get; }
+ /// <summary>
+ /// Gets the name of the telemetry source.
+ /// </summary>
+ string Name { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether the telemetry source requires duplication tracking.
+ /// If true, the system should ensure that duplicate telemetry from this source and another will be filtered.
+ /// </summary>
bool RequiresTelemetryDuplicationTracking { get; }
}
}
diff --git a/Software/Visual_Studio/Tango.Telemetry/ITelemetryStreamingSource.cs b/Software/Visual_Studio/Tango.Telemetry/ITelemetryStreamingSource.cs
index 3c60c35ee..725be0193 100644
--- a/Software/Visual_Studio/Tango.Telemetry/ITelemetryStreamingSource.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/ITelemetryStreamingSource.cs
@@ -1,15 +1,30 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace Tango.Telemetry
{
+ /// <summary>
+ /// Represents a telemetry source that emits real-time streaming telemetry.
+ /// </summary>
public interface ITelemetryStreamingSource : ITelemetrySource
{
+ /// <summary>
+ /// Occurs when new telemetry data is available to be processed.
+ /// </summary>
event EventHandler<TelemetryAvailableEventArgs> TelemetryAvailable;
+
+ /// <summary>
+ /// Gets a value indicating whether the streaming source is currently running.
+ /// </summary>
+ bool IsStarted { get; }
+
+ /// <summary>
+ /// Starts the telemetry streaming process.
+ /// </summary>
void Start();
+
+ /// <summary>
+ /// Stops the telemetry streaming process.
+ /// </summary>
void Stop();
}
}
diff --git a/Software/Visual_Studio/Tango.Telemetry/Mappers/JobRunMapper.cs b/Software/Visual_Studio/Tango.Telemetry/Mappers/JobRunMapper.cs
new file mode 100644
index 000000000..4a08f9645
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Telemetry/Mappers/JobRunMapper.cs
@@ -0,0 +1,320 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Data.Entity;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.BL.FineTuning;
+using Tango.Integration.JobRuns;
+using Tango.Integration.Operation;
+using Tango.Logging;
+using Tango.Telemetry.Telemetries;
+
+namespace Tango.Telemetry.Mappers
+{
+ public class JobRunMapper
+ {
+ private static List<ColorCatalog> _catalogs;
+ private static List<ColorCatalogsItem> _color_catalog_Items;
+ private static List<ColorSpace> _colorSpaces;
+ private static Dictionary<String, LiquidType> _liquidTypes;
+ private static List<Rml> _rmls;
+
+ private static Object _lock = new object();
+ private static bool _initialized;
+
+ private static void Init()
+ {
+ if (!_initialized)
+ {
+ lock (_lock)
+ {
+ if (!_initialized)
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ _colorSpaces = db.ColorSpaces.ToList();
+ _catalogs = db.ColorCatalogs.ToList();
+ _color_catalog_Items = db.ColorCatalogsItems.ToList();
+
+ var types = db.LiquidTypes.ToList();
+ _liquidTypes = new Dictionary<string, LiquidType>();
+
+ foreach (var t in types)
+ {
+ _liquidTypes.Add(t.Name, t);
+ }
+
+ _rmls = db.Rmls
+ .Select(x => new { x.Guid, x.Name, x.DisplayName })
+ .ToList()
+ .Select(x => new Rml() { Guid = x.Guid, Name = x.Name, DisplayName = x.DisplayName })
+ .ToList();
+ }
+
+ _initialized = true;
+ }
+ }
+ }
+ }
+
+ public static TelemetryJobRun MapJobRun(JobRun run)
+ {
+ Init();
+
+ var Logger = LogManager.Default;
+
+ TelemetryJobRun tRun = new TelemetryJobRun();
+
+ tRun.ID = run.Guid;
+ tRun.Time = run.LastUpdated;
+
+ tRun.JobName = run.JobName;
+ tRun.Kind = run.Designation.ToString();
+ tRun.Thread = _rmls.FirstOrDefault(x => x.Guid == run.RmlGuid)?.FinalName;
+ tRun.NumberOfUnits = Math.Max(run.NumberOfUnits, 1);
+
+ //What the user entered including white gaps leaving out spools and number of units.
+ tRun.LogicalLength = run.JobLogicalLength;
+
+ //What the user entered talking into account white gaps, spools and number of units.
+ //(White gaps between units is not calculated here and is added further here when the JobFile is ready with the inter-segment length).
+ tRun.ActualLength = (run.MachineTypeEnum == MachineTypes.Eureka ? run.JobLogicalLength * 4 : run.JobLogicalLength) * tRun.NumberOfUnits;
+
+ //The actual length the machine had ran, including white gap, spools, number of units and dryer buffer length.
+ tRun.TotalLength = run.MachineTypeEnum == MachineTypes.Eureka ? run.JobLength * 4 : run.JobLength;
+
+ tRun.StartPosition = run.MachineTypeEnum == MachineTypes.Eureka ? run.ActualStartPosition * 4 : run.ActualStartPosition;
+ tRun.EndPosition = (run.MachineTypeEnum == MachineTypes.Eureka ? 4 : 1) * (run.ActualEndPosition > 0 ? run.ActualEndPosition : run.EndPosition);
+ tRun.Distance = tRun.EndPosition - tRun.StartPosition;
+
+ tRun.StartTime = run.StartDate;
+ tRun.EndTime = run.EndDate;
+ tRun.Duration = tRun.EndTime - tRun.StartTime;
+ if (run.ActualStartDate != null && run.HeatingStartDate != null)
+ {
+ tRun.HeatingDuration = run.ActualStartDate.Value - run.HeatingStartDate.Value;
+ }
+
+ tRun.Status = run.JobRunStatus.ToString();
+
+ tRun.OutputCyan = run.CyanQuantity;
+ tRun.OutputMagenta = run.MagentaQuantity;
+ tRun.OutputYellow = run.YellowQuantity;
+ tRun.OutputBlack = run.BlackQuantity;
+ tRun.OutputLightCyan = run.LightCyanQuantity;
+ tRun.OutputLightMagenta = run.LightMagentaQuantity;
+ tRun.OutputLightYellow = run.LightYellowQuantity;
+ tRun.OutputBlue = run.BlueQuantity;
+ tRun.OutputLightBlue = run.LightBlueQuantity;
+ tRun.OutputOrange = run.OrangeQuantity;
+ tRun.OutputLightOrange = run.LightOrangeQuantity;
+ tRun.OutputRubine = run.RubineQuantity;
+ tRun.OutputLightRubine = run.LightRubineQuantity;
+ tRun.OutputNavy = run.NavyQuantity;
+ tRun.OutputViolet = run.VioletQuantity;
+ tRun.OutputTransparent = run.TransparentQuantity;
+ tRun.OutputLubricant = run.LubricantQuantity;
+
+ tRun.FailureReason = run.FailedMessage;
+
+ tRun.ApplicationVersion = run.ApplicationVersion;
+ tRun.FirmwareVersion = run.FirmwareVersion;
+
+
+ try
+ {
+ if (run.JobFile != null)
+ {
+ tRun.InterSegmentLength = run.JobFile.EnableInterSegment ? (int)run.JobFile.InterSegmentLength : 0;
+ tRun.LubricationEnabled = run.JobFile.EnableLubrication;
+ tRun.SpoolTypeDistribution = run.JobFile.SpoolsDistribution;
+ tRun.NumberOfSpools = Math.Max(run.JobFile.NumberOfSpools, 1);
+
+ //Fix the ActualLength by adding all white gaps missing for the number of units.
+ if (tRun.InterSegmentLength > 0)
+ {
+ double unitsWhiteGapAddition = tRun.InterSegmentLength * (tRun.NumberOfUnits - 1);
+ tRun.ActualLength += unitsWhiteGapAddition * (run.MachineTypeEnum == MachineTypes.Eureka ? 4 : 1);
+ }
+
+ tRun.Segments = new List<TelemetryJobRun.TelemetryJobRunSegment>();
+
+ int sIndex = 0;
+
+ foreach (var segment in run.JobFile.Segments)
+ {
+ try
+ {
+ var tSegment = new TelemetryJobRun.TelemetryJobRunSegment();
+ tSegment.Index = sIndex++;
+ tSegment.Length = segment.Length;
+ tRun.Segments.Add(tSegment);
+
+ foreach (var stop in segment.BrushStops.OrderBy(x => x.StopIndex))
+ {
+ try
+ {
+ var tStop = new TelemetryJobRun.TelemetryJobRunBrushStop();
+ tStop.Index = stop.StopIndex;
+ tStop.OffsetPercent = stop.OffsetPercent;
+
+ tStop.ColorSpace = _colorSpaces.FirstOrDefault(x => x.Guid == stop.ColorSpaceGuid)?.Name;
+
+ tStop.Red = stop.Red;
+ tStop.Green = stop.Green;
+ tStop.Blue = stop.Blue;
+
+ tStop.L = stop.L;
+ tStop.A = stop.A;
+ tStop.B = stop.B;
+
+ if (stop.ColorCatalogGuid != null)
+ {
+ tStop.Catalog = _catalogs.FirstOrDefault(x => x.Guid == stop.ColorCatalogGuid)?.Name;
+
+ if (stop.ColorCatalogItemGuid != null)
+ {
+ tStop.CatalogItem = _color_catalog_Items.FirstOrDefault(x => x.Guid == stop.ColorCatalogItemGuid)?.Name;
+ }
+ }
+
+ tStop.BestMatchR = stop.BestMatchR;
+ tStop.BestMatchG = stop.BestMatchG;
+ tStop.BestMatchB = stop.BestMatchB;
+
+ tSegment.Stops.Add(tStop);
+
+ //Volume Output
+ foreach (var liquidType in _liquidTypes.Select(x => x.Value).OrderBy(x => x.PreferredIndex))
+ {
+ try
+ {
+ var tLiquid = new TelemetryJobRun.TelemetryJobRunBrushStopLiquidVolume();
+ tLiquid.LiquidType = liquidType.Name;
+
+ var liquidVolume = stop.LiquidVolumes.FirstOrDefault(x => x.LiquidTypeName == liquidType.Name);
+
+ if (liquidVolume != null)
+ {
+ tLiquid.Volume = liquidVolume.Volume;
+ }
+
+ tStop.OutputVolumes.Add(tLiquid);
+ }
+ catch (Exception ex)
+ {
+ Logger.Log(ex, $"Error mapping volume output for JobRun '{run.JobName} -> Segment {sIndex} -> Stop {stop.StopIndex} -> Liquid {liquidType.Name}'.");
+ }
+ }
+
+ //Volume Input
+ foreach (var liquidType in _liquidTypes.Select(x => x.Value).Where(x => x.HasPigment).OrderBy(x => x.PreferredIndex))
+ {
+ try
+ {
+ var tLiquid = new TelemetryJobRun.TelemetryJobRunBrushStopLiquidVolume();
+ tLiquid.LiquidType = liquidType.Name;
+
+ var liquidVolume = stop.LiquidVolumes.FirstOrDefault(x => x.LiquidTypeName == liquidType.Name);
+
+ if (liquidVolume != null)
+ {
+ tLiquid.Volume = liquidVolume.Volume;
+ }
+
+ tStop.InputVolumes.Add(tLiquid);
+ }
+ catch (Exception ex)
+ {
+ Logger.Log(ex, $"Error mapping volume input for JobRun '{run.JobName} -> Segment {sIndex} -> Stop {stop.StopIndex} -> Liquid {liquidType.Name}'.");
+ }
+ }
+
+ //Normalize Light/Dark Inks Inputs
+ foreach (var input in tStop.InputVolumes.ToList())
+ {
+ try
+ {
+ var inputType = _liquidTypes[input.LiquidType];
+
+ if (inputType.IsLightInk && input.Volume > 0)
+ {
+ var darkInkType = _liquidTypes.Select(x => x.Value).FirstOrDefault(x => x.Code == inputType.DarkInkCode);
+ if (darkInkType != null)
+ {
+ var darkInkVolume = tStop.InputVolumes.FirstOrDefault(x => x.LiquidType == darkInkType.Name);
+ if (darkInkVolume != null)
+ {
+ darkInkVolume.Volume = (double)((decimal)input.Volume / 10m);
+ input.Volume = 0;
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.Log(ex, $"Error normalizing volume input for JobRun '{run.JobName} -> Segment {sIndex} -> Stop {stop.StopIndex} -> Liquid {input.LiquidType}'.");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ //Issue with stop
+ Logger.Log(ex, $"Error mapping stop for JobRun '{run.JobName} -> Segment {sIndex} -> Stop {stop.StopIndex}'.");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ //Issue with segment.
+ Logger.Log(ex, $"Error mapping segment for JobRun '{run.JobName} -> Segment {sIndex}'.");
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.Log(ex, $"Error mapping job file for JobRun '{run.JobName}'.");
+ }
+
+ try
+ {
+ if (run.FineTuningString != null)
+ {
+ tRun.FineTuning = JsonConvert.DeserializeObject<VectorFineTuningRunModel>(run.FineTuningString);
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.Log(ex, $"Error mapping fine tuning model for JobRun '{run.JobName}'.");
+ }
+
+ try
+ {
+ var jobRunsFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Twine", "Tango", "JobRuns Extended Info");
+
+ String filePath = Path.Combine(jobRunsFolder, $"{run.ID}.run");
+
+ if (File.Exists(filePath))
+ {
+ String json = File.ReadAllText(filePath);
+
+ JobRunInfo info = JsonConvert.DeserializeObject<JobRunInfo>(json);
+ tRun.ProcessParameters = info.JobTicket.ProcessParameters;
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.Log(ex, $"Error mapping extended info for JobRun '{run.JobName}'.");
+ }
+
+ return tRun;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryDiagnosticsSource.cs b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryDiagnosticsSource.cs
index 5a2735131..37a8d224d 100644
--- a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryDiagnosticsSource.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryDiagnosticsSource.cs
@@ -19,7 +19,6 @@ namespace Tango.Telemetry.Sources
public const int MIN_SAMPLING_INTERVAL_SECONDS = 1;
private IMachineOperator _machineOperator;
- private bool _isStarted;
private Timer _diagnosticsSamplingTimer;
private List<StartDiagnosticsResponse> _diagnosticsQueue;
@@ -31,6 +30,7 @@ namespace Tango.Telemetry.Sources
public string Name { get; private set; } = "Diagnostics";
public bool RequiresTelemetryDuplicationTracking { get => false; }
+ public bool IsStarted { get; private set; }
private TelemetryDiagnosticsSource() : base()
{
@@ -45,7 +45,7 @@ namespace Tango.Telemetry.Sources
private void DiagnosticsDataAvailable(object sender, StartDiagnosticsResponse diagnostics)
{
- if (_isStarted && diagnostics.Monitors != null)
+ if (IsStarted && diagnostics.Monitors != null)
{
_diagnosticsQueue.Add(diagnostics);
}
@@ -53,7 +53,7 @@ namespace Tango.Telemetry.Sources
public void Start()
{
- _isStarted = true;
+ IsStarted = true;
if (Config.DiagnosticsSamplingInterval.TotalSeconds < MIN_SAMPLING_INTERVAL_SECONDS)
{
@@ -76,12 +76,12 @@ namespace Tango.Telemetry.Sources
public void Stop()
{
- _isStarted = false;
+ IsStarted = false;
}
private void DiagnosticsSamplingTimer_Elapsed(object sender, ElapsedEventArgs e)
{
- if (!_isStarted || _writing) return;
+ if (!IsStarted || _writing) return;
try
{
@@ -103,7 +103,7 @@ namespace Tango.Telemetry.Sources
frame.Time = DateTime.UtcNow.Subtract(Config.DiagnosticsSamplingInterval);
- TelemetryAvailable?.Invoke(this, new TelemetryAvailableEventArgs(frame, TelemetrySourceTypes.Streaming));
+ TelemetryAvailable?.Invoke(this, new TelemetryAvailableEventArgs() { TelemetryObject = frame });
}
else
{
@@ -112,7 +112,7 @@ namespace Tango.Telemetry.Sources
TelemetryDiagnosticsFrame frame = new TelemetryDiagnosticsFrame();
frame.Monitors = new InsightsMonitors();
frame.Time = DateTime.UtcNow.Subtract(Config.DiagnosticsSamplingInterval);
- TelemetryAvailable?.Invoke(this, new TelemetryAvailableEventArgs(frame, TelemetrySourceTypes.Streaming));
+ TelemetryAvailable?.Invoke(this, new TelemetryAvailableEventArgs() { TelemetryObject = frame });
_emptyWritten = true;
}
}
diff --git a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobRunsHistorySource.cs b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobRunsHistorySource.cs
index e3934d832..b13402831 100644
--- a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobRunsHistorySource.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobRunsHistorySource.cs
@@ -5,6 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.BL;
+using Tango.Telemetry.Mappers;
using Tango.Telemetry.Telemetries;
namespace Tango.Telemetry.Sources
@@ -13,13 +14,23 @@ namespace Tango.Telemetry.Sources
{
private bool _isBusy;
- public string Name { get; private set; } = "JobRuns History";
-
+ public string Name { get;} = "JobRuns History";
public bool RequiresTelemetryDuplicationTracking { get => true; }
+ public TelemetryHistorySourceDirection Direction { get => TelemetryHistorySourceDirection.Descending; }
- public Task<bool> CanRequestHistory(DateTime from)
+ public async Task<bool> CanRequestHistory(DateTime from)
{
- return Task.FromResult(!_isBusy);
+ if (_isBusy)
+ {
+ return false;
+ }
+ else
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ return await db.JobRuns.CountAsync(x => x.LastUpdated < from) > 0;
+ }
+ }
}
public async Task<IEnumerable<ITelemetry>> RequestHistory(DateTime from)
@@ -31,8 +42,8 @@ namespace Tango.Telemetry.Sources
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
var runs = await db.JobRuns
- .Where(x => x.LastUpdated > from)
- .OrderBy(x => x.LastUpdated)
+ .OrderByDescending(x => x.LastUpdated)
+ .Where(x => x.LastUpdated < from)
.Take(Config.MaxJobRunsPerRequest)
.ToListAsync();
@@ -40,11 +51,7 @@ namespace Tango.Telemetry.Sources
foreach (var run in runs)
{
- TelemetryJobRun tRun = new TelemetryJobRun();
- tRun.ID = run.Guid;
- tRun.Time = run.LastUpdated;
- tRun.Name = run.JobName;
- //Fill the object..
+ var tRun = JobRunMapper.MapJobRun(run);
tRuns.Add(tRun);
}
diff --git a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobRunsStreamingSource.cs b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobRunsStreamingSource.cs
new file mode 100644
index 000000000..b3199eb36
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobRunsStreamingSource.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core;
+using Tango.Integration.Operation;
+using Tango.Telemetry.Mappers;
+
+namespace Tango.Telemetry.Sources
+{
+ public class TelemetryJobRunsStreamingSource : ExtendedObject, ITelemetryStreamingSource
+ {
+ private IMachineOperator _machineOperator;
+
+ public string Name { get; } = "JobRuns Streaming";
+
+ public bool RequiresTelemetryDuplicationTracking { get; } = true;
+ public bool IsStarted { get; private set; }
+
+ public event EventHandler<TelemetryAvailableEventArgs> TelemetryAvailable;
+
+ public TelemetryJobRunsStreamingSource(IMachineOperator machineOperator)
+ {
+ _machineOperator = machineOperator;
+ }
+
+ private void JobRunsLogger_JobRunAvailable(object sender, Integration.JobRuns.JobRunAvailableEventArgs e)
+ {
+ Task.Factory.StartNew(() =>
+ {
+ if (IsStarted)
+ {
+ var tRun = JobRunMapper.MapJobRun(e.JobRun);
+ TelemetryAvailable?.Invoke(this, new TelemetryAvailableEventArgs() { TelemetryObject = tRun });
+ }
+ });
+ }
+
+ public void Dispose()
+ {
+ Stop();
+ }
+
+ public void Start()
+ {
+ if (!IsStarted)
+ {
+ _machineOperator.JobRunsLogger.JobRunAvailable += JobRunsLogger_JobRunAvailable;
+ IsStarted = true;
+ }
+ }
+
+ public void Stop()
+ {
+ if (IsStarted)
+ {
+ _machineOperator.JobRunsLogger.JobRunAvailable -= JobRunsLogger_JobRunAvailable;
+ IsStarted = false;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Telemetry/Tango.Telemetry.csproj b/Software/Visual_Studio/Tango.Telemetry/Tango.Telemetry.csproj
index 9565465a5..ff1fcb43e 100644
--- a/Software/Visual_Studio/Tango.Telemetry/Tango.Telemetry.csproj
+++ b/Software/Visual_Studio/Tango.Telemetry/Tango.Telemetry.csproj
@@ -55,6 +55,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="Google.Protobuf, Version=3.4.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
+ <HintPath>..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.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>
@@ -247,6 +250,7 @@
<Compile Include="ITelemetryStorageManager.cs" />
<Compile Include="ITelemetryPublisher.cs" />
<Compile Include="ITelemetryStreamingSource.cs" />
+ <Compile Include="Mappers\JobRunMapper.cs" />
<Compile Include="Reporting\DestinationStatusSummary.cs" />
<Compile Include="Reporting\SourceSummary.cs" />
<Compile Include="Reporting\SourceTypeSummary.cs" />
@@ -256,8 +260,10 @@
<Compile Include="Sources\TelemetryJobRunsHistorySource.cs" />
<Compile Include="Sources\TelemetryJobRunsHistorySourceConfig.cs" />
<Compile Include="PendingTelemetry.cs" />
+ <Compile Include="Sources\TelemetryJobRunsStreamingSource.cs" />
<Compile Include="TelemetryConfigurableSource.cs" />
<Compile Include="TelemetryHistorySourceCheckPoint.cs" />
+ <Compile Include="TelemetryHistorySourceDirection.cs" />
<Compile Include="TelemetryNameAttribute.cs" />
<Compile Include="TelemetryAvailableEventArgs.cs" />
<Compile Include="TelemetryPackagePublishedEventArgs.cs" />
@@ -265,7 +271,7 @@
<Compile Include="TelemetryPendingDestination.cs" />
<Compile Include="TelemetryPendingStorageSource.cs" />
<Compile Include="TelemetryInMemoryQueueManager.cs" />
- <None Include="app.config" />
+ <Compile Include="TelemetryStreamingAvailableEventArgs.cs" />
<None Include="TelemetryPublisherAdvanced.cs" />
<Compile Include="TelemetryPublisherEventArgs.cs" />
<Compile Include="TelemetryPackagePublishingEventArgs.cs" />
diff --git a/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryDiagnosticsFrame.cs b/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryDiagnosticsFrame.cs
index da64c50a0..358ce7e70 100644
--- a/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryDiagnosticsFrame.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryDiagnosticsFrame.cs
@@ -10,7 +10,7 @@ using Tango.PMR.Insights;
namespace Tango.Telemetry.Telemetries
{
- [TelemetryName("DiagnosticsFrame")]
+ [TelemetryName("DiagnosticsFrame", 1)]
public class TelemetryDiagnosticsFrame : TelemetryBase
{
public InsightsMonitors Monitors { get; set; }
diff --git a/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryJobRun.cs b/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryJobRun.cs
index 5aca89ee0..502b6397f 100644
--- a/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryJobRun.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryJobRun.cs
@@ -3,19 +3,79 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Tango.BL.Enumerations;
+using Tango.BL.FineTuning;
+using Tango.Integration.JobRuns;
+using Tango.PMR.Printing;
namespace Tango.Telemetry.Telemetries
{
- [TelemetryName("JobRun")]
+ [TelemetryName("JobRun", 1)]
public class TelemetryJobRun : TelemetryBase
{
- public String Name { get; set; }
- public String JobKind { get; set; }
+ public class TelemetryJobRunSegment
+ {
+ public int Index { get; set; }
+ public double Length { get; set; }
+
+ public List<TelemetryJobRunBrushStop> Stops { get; set; }
+
+ public TelemetryJobRunSegment()
+ {
+ Stops = new List<TelemetryJobRunBrushStop>();
+ }
+ }
+
+ public class TelemetryJobRunBrushStop
+ {
+ public int Index { get; set; }
+ public double OffsetPercent { get; set; }
+
+ public String ColorSpace { get; set; }
+
+ public int Red { get; set; }
+ public int Green { get; set; }
+ public int Blue { get; set; }
+
+ public double L { get; set; }
+ public double A { get; set; }
+ public double B { get; set; }
+
+ public String Catalog { get; set; }
+ public String CatalogItem { get; set; }
+
+ public int BestMatchR { get; set; }
+ public int BestMatchG { get; set; }
+ public int BestMatchB { get; set; }
+
+ public List<TelemetryJobRunBrushStopLiquidVolume> InputVolumes { get; set; }
+ public List<TelemetryJobRunBrushStopLiquidVolume> OutputVolumes { get; set; }
+
+ public TelemetryJobRunBrushStop()
+ {
+ InputVolumes = new List<TelemetryJobRunBrushStopLiquidVolume>();
+ OutputVolumes = new List<TelemetryJobRunBrushStopLiquidVolume>();
+ }
+ }
+
+ public class TelemetryJobRunBrushStopLiquidVolume
+ {
+ public String LiquidType { get; set; }
+ public double Volume { get; set; }
+ }
+
+ public String JobName { get; set; }
+ public String Kind { get; set; }
public String Thread { get; set; }
- public String NumberOfUnits { get; set; }
+ public int NumberOfUnits { get; set; }
+ public int InterSegmentLength { get; set; }
+ public bool LubricationEnabled { get; set; }
+ public int SpoolTypeDistribution { get; set; }
+ public int NumberOfSpools { get; set; }
public double LogicalLength { get; set; }
public double ActualLength { get; set; }
+ public double TotalLength { get; set; }
public double StartPosition { get; set; }
public double EndPosition { get; set; }
public double Distance { get; set; }
@@ -23,15 +83,42 @@ namespace Tango.Telemetry.Telemetries
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public TimeSpan Duration { get; set; }
+ public TimeSpan HeatingDuration { get; set; }
public String Status { get; set; }
- public String ColorSpace { get; set; }
+ public long OutputCyan { get; set; }
+ public long OutputMagenta { get; set; }
+ public long OutputYellow { get; set; }
+ public long OutputBlack { get; set; }
+ public long OutputLightCyan { get; set; }
+ public long OutputLightMagenta { get; set; }
+ public long OutputLightYellow { get; set; }
+ public long OutputBlue { get; set; }
+ public long OutputLightBlue { get; set; }
+ public long OutputOrange { get; set; }
+ public long OutputLightOrange { get; set; }
+ public long OutputRubine { get; set; }
+ public long OutputLightRubine { get; set; }
+ public long OutputNavy { get; set; }
+ public long OutputViolet { get; set; }
+ public long OutputTransparent { get; set; }
+ public long OutputLubricant { get; set; }
+
+ public String FailureReason { get; set; }
+
+ public String ApplicationVersion { get; set; }
+ public String FirmwareVersion { get; set; }
+
+ public List<TelemetryJobRunSegment> Segments { get; set; } //Dynamic
- public double TargetL { get; set; }
- public double TargetA { get; set; }
- public double TargetB { get; set; }
+ public VectorFineTuningRunModel FineTuning { get; set; } //Dynamic
+ public ProcessParameters ProcessParameters { get; set; } //Dynamic
+ public TelemetryJobRun()
+ {
+ Segments = new List<TelemetryJobRunSegment>();
+ }
}
}
diff --git a/Software/Visual_Studio/Tango.Telemetry/TelemetryAvailableEventArgs.cs b/Software/Visual_Studio/Tango.Telemetry/TelemetryAvailableEventArgs.cs
index a9ddf890c..c55ea2fab 100644
--- a/Software/Visual_Studio/Tango.Telemetry/TelemetryAvailableEventArgs.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/TelemetryAvailableEventArgs.cs
@@ -8,13 +8,6 @@ namespace Tango.Telemetry
{
public class TelemetryAvailableEventArgs : EventArgs
{
- public TelemetrySourceTypes SourceType { get; set; }
public ITelemetry TelemetryObject { get; set; }
-
- public TelemetryAvailableEventArgs(ITelemetry telemetryObject, TelemetrySourceTypes source)
- {
- TelemetryObject = telemetryObject;
- SourceType = source;
- }
}
}
diff --git a/Software/Visual_Studio/Tango.Telemetry/TelemetryHistorySourceDirection.cs b/Software/Visual_Studio/Tango.Telemetry/TelemetryHistorySourceDirection.cs
new file mode 100644
index 000000000..036176e6f
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Telemetry/TelemetryHistorySourceDirection.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Tango.Telemetry
+{
+ /// <summary>
+ /// Specifies the direction in which historical telemetry data should be published.
+ /// </summary>
+ public enum TelemetryHistorySourceDirection
+ {
+ /// <summary>
+ /// Indicates that historical telemetry should be published in chronological order, from oldest to newest.
+ /// </summary>
+ Ascending,
+
+ /// <summary>
+ /// Indicates that historical telemetry should be published in reverse chronological order, from newest to oldest.
+ /// </summary>
+ Descending,
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.Telemetry/TelemetryLiteDBStorageManager.cs b/Software/Visual_Studio/Tango.Telemetry/TelemetryLiteDBStorageManager.cs
index 6700ba8af..70b1f6f18 100644
--- a/Software/Visual_Studio/Tango.Telemetry/TelemetryLiteDBStorageManager.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/TelemetryLiteDBStorageManager.cs
@@ -176,14 +176,6 @@ namespace Tango.Telemetry
{
var collection = GetSourcesCheckpointCollection();
var checkpoint = collection.FindOne(x => x.SourceName == source.Name);
-
- if (checkpoint == null)
- {
- checkpoint = new TelemetryHistorySourceCheckPoint();
- checkpoint.SourceName = source.Name;
- checkpoint.Time = DateTime.MinValue;
- }
-
return checkpoint;
}
}
@@ -200,10 +192,13 @@ namespace Tango.Telemetry
public void SetHistorySourceCheckPoint(ITelemetryHistorySource source, DateTime time, int totalCount)
{
+ var a = time.Kind;
lock (_lock)
{
+ DateTime utcTime = DateTime.SpecifyKind(time, DateTimeKind.Utc);
+
var collection = GetSourcesCheckpointCollection();
- collection.Upsert(new TelemetryHistorySourceCheckPoint() { SourceName = source.Name, Time = time, TotalCount = totalCount });
+ collection.Upsert(new TelemetryHistorySourceCheckPoint() { SourceName = source.Name, Time = utcTime, TotalCount = totalCount });
if (_checkpointsRecoveryClient != null && DateTime.UtcNow - _lastCloudBackupTime > CheckpointsBackupInterval)
{
diff --git a/Software/Visual_Studio/Tango.Telemetry/TelemetryNameAttribute.cs b/Software/Visual_Studio/Tango.Telemetry/TelemetryNameAttribute.cs
index f6adb2d61..5af71c926 100644
--- a/Software/Visual_Studio/Tango.Telemetry/TelemetryNameAttribute.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/TelemetryNameAttribute.cs
@@ -10,9 +10,12 @@ namespace Tango.Telemetry
{
public String Name { get; set; }
- public TelemetryNameAttribute(String name)
+ public int Version { get; set; }
+
+ public TelemetryNameAttribute(String name, int version)
{
Name = name;
+ Version = version;
}
}
}
diff --git a/Software/Visual_Studio/Tango.Telemetry/TelemetryPublishPackage.cs b/Software/Visual_Studio/Tango.Telemetry/TelemetryPublishPackage.cs
index 7b6b577a0..b008a210f 100644
--- a/Software/Visual_Studio/Tango.Telemetry/TelemetryPublishPackage.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/TelemetryPublishPackage.cs
@@ -19,7 +19,10 @@ namespace Tango.Telemetry
public String Environment { get; set; }
public String SerialNumber { get; set; }
public String MachineType { get; set; }
+ public String Organization { get; internal set; }
+ public String Site { get; internal set; }
public String TelemetryName { get; internal set; }
+ public int TelemetryVersion { get; internal set; }
public TelemetryPublishPackage()
{
diff --git a/Software/Visual_Studio/Tango.Telemetry/TelemetryPublisher.cs b/Software/Visual_Studio/Tango.Telemetry/TelemetryPublisher.cs
index 42121d884..4c91e6733 100644
--- a/Software/Visual_Studio/Tango.Telemetry/TelemetryPublisher.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/TelemetryPublisher.cs
@@ -194,8 +194,8 @@ namespace Tango.Telemetry
var source = sender as ITelemetrySource;
if (source != null)
{
- LogManager.Log($"Telemetry stream received {source.Name} -> {e.SourceType} -> {e.TelemetryObject.ToTelemetryName()}.", LogCategory.Debug);
- PushTelemetryPackage(source, e.TelemetryObject, e.SourceType);
+ LogManager.Log($"Telemetry stream received {source.Name} -> {e.TelemetryObject.ToTelemetryName()}.", LogCategory.Debug);
+ PushTelemetryPackage(source, e.TelemetryObject, TelemetrySourceTypes.Streaming);
}
}
@@ -408,29 +408,45 @@ namespace Tango.Telemetry
{
try
{
- TelemetryHistorySourceCheckPoint checkPoint = StorageManager.GetHistorySourceCheckPoint(source);
+ TelemetryHistorySourceCheckPoint checkpoint = StorageManager.GetHistorySourceCheckPoint(source);
- LogManager.Log($"Evaluating history source '{source.Name}' at checkpoint time {checkPoint?.Time:u}", LogCategory.Debug);
+ if (checkpoint == null)
+ {
+ checkpoint = new TelemetryHistorySourceCheckPoint();
+ checkpoint.SourceName = source.Name;
+ checkpoint.Time = source.Direction == TelemetryHistorySourceDirection.Ascending ? DateTime.MinValue : DateTime.MaxValue;
+ }
- if (await source.CanRequestHistory(checkPoint.Time))
+ LogManager.Log($"Evaluating history source '{source.Name}' at checkpoint time {checkpoint?.Time:u}", LogCategory.Debug);
+
+ if (await source.CanRequestHistory(checkpoint.Time))
{
- var historyTelemetries = (await source.RequestHistory(checkPoint.Time)).OrderBy(x => x.Time).ToList();
+ List<ITelemetry> historyTelemetries = new List<ITelemetry>();
+
+ if (source.Direction == TelemetryHistorySourceDirection.Ascending)
+ {
+ historyTelemetries = (await source.RequestHistory(checkpoint.Time)).OrderBy(x => x.Time).ToList();
+ }
+ else
+ {
+ historyTelemetries = (await source.RequestHistory(checkpoint.Time)).OrderByDescending(x => x.Time).ToList();
+ }
LogManager.Log($"History source '{source.Name}' returned {historyTelemetries.Count} telemetry items.", LogCategory.Debug);
foreach (var telemetry in historyTelemetries)
{
await PushTelemetryPackageAwait(source, telemetry, TelemetrySourceTypes.ExternalStorage);
- checkPoint.Time = telemetry.Time;
- checkPoint.TotalCount++;
- StorageManager.SetHistorySourceCheckPoint(source, checkPoint.Time, checkPoint.TotalCount);
+ checkpoint.Time = telemetry.Time;
+ checkpoint.TotalCount++;
+ StorageManager.SetHistorySourceCheckPoint(source, checkpoint.Time, checkpoint.TotalCount);
}
- LogManager.Log($"Checkpoint updated for source '{source.Name}': time = {checkPoint.Time:u}, total = {checkPoint.TotalCount}", LogCategory.Debug);
+ LogManager.Log($"Checkpoint updated for source '{source.Name}': time = {checkpoint.Time:u}, total = {checkpoint.TotalCount}", LogCategory.Debug);
}
else
{
- LogManager.Log($"History request for source '{source.Name}' was not permitted at checkpoint time {checkPoint?.Time:u}", LogCategory.Debug);
+ LogManager.Log($"History request for source '{source.Name}' was not permitted at checkpoint time {checkpoint?.Time:u}", LogCategory.Debug);
}
}
catch (Exception ex)
@@ -610,17 +626,23 @@ namespace Tango.Telemetry
// Prepare standard metadata properties attached to all telemetry sent
var telemetryName = package.PendingTelemetry.TelemetryObject.ToTelemetryName();
+ var telemetryVersion = package.PendingTelemetry.TelemetryObject.ToTelemetryVersion();
List<KeyValuePair<String, String>> properties = new List<KeyValuePair<string, string>>();
properties.Add(new KeyValuePair<string, string>("SerialNumber", Config.SerialNumber));
properties.Add(new KeyValuePair<string, string>("MachineType", Config.MachineType.ToShortName()));
+ properties.Add(new KeyValuePair<string, string>("Organization", Config.Organization));
+ properties.Add(new KeyValuePair<string, string>("Site", Config.Site));
properties.Add(new KeyValuePair<string, string>("Environment", Config.Environment));
properties.Add(new KeyValuePair<string, string>("Type", telemetryName));
//Setting telemetry package basic properties for destination..
package.TelemetryName = telemetryName;
+ package.TelemetryVersion = telemetryVersion;
package.SerialNumber = Config.SerialNumber;
package.Environment = Config.Environment;
+ package.Organization = Config.Organization;
+ package.Site = Config.Site;
package.MachineType = Config.MachineType.ToShortName();
diff --git a/Software/Visual_Studio/Tango.Telemetry/TelemetryPublisherConfiguration.cs b/Software/Visual_Studio/Tango.Telemetry/TelemetryPublisherConfiguration.cs
index a9f4954dd..ceb405a4e 100644
--- a/Software/Visual_Studio/Tango.Telemetry/TelemetryPublisherConfiguration.cs
+++ b/Software/Visual_Studio/Tango.Telemetry/TelemetryPublisherConfiguration.cs
@@ -15,6 +15,10 @@ namespace Tango.Telemetry
/// </summary>
public MachineTypes MachineType { get; set; }
+ public String Organization { get; set; }
+
+ public String Site { get; set; }
+
/// <summary>
/// Environment in which the telemetry is being published (e.g., Production, QA, Dev).
/// </summary>
@@ -23,27 +27,27 @@ namespace Tango.Telemetry
/// <summary>
/// Interval for checking and reprocessing failed/pending telemetry from local storage.
/// </summary>
- public TimeSpan PendingStorageCheckInterval { get; set; }
+ public TimeSpan PendingStorageCheckInterval { get; set; } = TimeSpan.FromMinutes(1);
/// <summary>
/// Maximum number of pending telemetry records to process in a single retry cycle.
/// </summary>
- public int MaxPendingStorageTelemetriesPerCycle { get; set; }
+ public int MaxPendingStorageTelemetriesPerCycle { get; set; } = 100;
/// <summary>
/// Frequency at which historical sources are polled to request backlogged or missed telemetry.
/// </summary>
- public TimeSpan HistorySourcesRequestInterval { get; set; }
+ public TimeSpan HistorySourcesRequestInterval { get; set; } = TimeSpan.FromMinutes(1);
/// <summary>
/// Maximum number of telemetry packages allowed in memory queues before rejecting new packages.
/// </summary>
- public int MaxPendingTelemetries { get; set; }
+ public int MaxPendingTelemetries { get; set; } = 200;
/// <summary>
/// Whether exponential backoff should be applied to retry logic per destination.
/// </summary>
- public bool EnableBackoff { get; set; }
+ public bool EnableBackoff { get; set; } = false;
/// <summary>
/// The maximum amount of time to delay retries during exponential backoff.
@@ -57,14 +61,6 @@ namespace Tango.Telemetry
/// </summary>
public TimeSpan PublishedTelemetriesCacheCleanupInterval { get; set; } = TimeSpan.FromHours(1);
- public TelemetryPublisherConfiguration()
- {
- PendingStorageCheckInterval = TimeSpan.FromMinutes(1);
- MaxPendingStorageTelemetriesPerCycle = 100;
- HistorySourcesRequestInterval = TimeSpan.FromMinutes(1);
- MaxPendingTelemetries = 200;
- }
-
public void Validate()
{
if (!SerialNumber.IsNotNullOrEmpty())
diff --git a/Software/Visual_Studio/Tango.Telemetry/TelemetryStreamingAvailableEventArgs.cs b/Software/Visual_Studio/Tango.Telemetry/TelemetryStreamingAvailableEventArgs.cs
new file mode 100644
index 000000000..81c55c9cf
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Telemetry/TelemetryStreamingAvailableEventArgs.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Telemetry
+{
+ public class TelemetryStreamingAvailableEventArgs : EventArgs
+ {
+ public ITelemetry Telemetry { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Telemetry/app.config b/Software/Visual_Studio/Tango.Telemetry/app.config
deleted file mode 100644
index 601f6dd75..000000000
--- a/Software/Visual_Studio/Tango.Telemetry/app.config
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
- <runtime>
- <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
- <dependentAssembly>
- <assemblyIdentity name="System.Runtime.InteropServices.RuntimeInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="Microsoft.Azure.Amqp" publicKeyToken="31bf3856ad364e35" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-2.4.0.0" newVersion="2.4.0.0" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="Microsoft.WindowsAzure.Storage" publicKeyToken="31bf3856ad364e35" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-8.7.0.0" newVersion="8.7.0.0" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="DotNetty.Transport" publicKeyToken="bc13ca065fa06c29" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-0.6.0.0" newVersion="0.6.0.0" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="DotNetty.Buffers" publicKeyToken="bc13ca065fa06c29" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-0.6.0.0" newVersion="0.6.0.0" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="DotNetty.Codecs.Mqtt" publicKeyToken="bc13ca065fa06c29" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-0.6.0.0" newVersion="0.6.0.0" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="DotNetty.Common" publicKeyToken="bc13ca065fa06c29" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-0.6.0.0" newVersion="0.6.0.0" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="DotNetty.Handlers" publicKeyToken="bc13ca065fa06c29" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-0.6.0.0" newVersion="0.6.0.0" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="System.Reactive.Core" publicKeyToken="94bc3704cddfc263" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-3.0.3000.0" newVersion="3.0.3000.0" />
- </dependentAssembly>
- </assemblyBinding>
- </runtime>
-</configuration> \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.Telemetry/packages.config b/Software/Visual_Studio/Tango.Telemetry/packages.config
index 027500d67..f15b9fef6 100644
--- a/Software/Visual_Studio/Tango.Telemetry/packages.config
+++ b/Software/Visual_Studio/Tango.Telemetry/packages.config
@@ -8,6 +8,7 @@
<package id="DotNetty.Transport" version="0.6.0" targetFramework="net461" />
<package id="EnterpriseLibrary.TransientFaultHandling" version="6.0.1304.0" targetFramework="net461" />
<package id="EntityFramework" version="6.2.0" targetFramework="net461" />
+ <package id="Google.Protobuf" version="3.4.1" targetFramework="net461" />
<package id="LiteDB" version="5.0.4" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net461" />
<package id="Microsoft.Azure.Amqp" version="2.5.10" targetFramework="net461" />
diff --git a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/App.config b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/App.config
index 959eb4686..60556a8ed 100644
--- a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/App.config
+++ b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/App.config
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
- <startup>
- <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
- </startup>
+ <configSections>
+ <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
+ <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+ </configSections>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
+ </startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
@@ -31,4 +35,10 @@
</dependentAssembly>
</assemblyBinding>
</runtime>
+ <entityFramework>
+ <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
+ <providers>
+ <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
+ </providers>
+ </entityFramework>
</configuration> \ No newline at end of file
diff --git a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Program.cs b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Program.cs
index cb8a79288..0565ab00d 100644
--- a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Program.cs
+++ b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Program.cs
@@ -3,8 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Tango.BL;
using Tango.BL.Enumerations;
+using Tango.Logging;
using Tango.Telemetry.Destinations;
+using Tango.Telemetry.Mappers;
using Tango.Telemetry.Sources;
namespace Tango.Telemetry.Tester.IOT.CLI
@@ -13,10 +16,13 @@ namespace Tango.Telemetry.Tester.IOT.CLI
{
static void Main(string[] args)
{
+ LogManager.Default.RegisterLogger(new Tango.Logging.VSOutputLogger("IOT TESTER"));
+
TelemetryPublisher publisher = new TelemetryPublisher(new TelemetryPublisherConfiguration()
{
Environment = "DEV",
SerialNumber = "dev-machine",
+ Organization = "Twine",
MachineType = MachineTypes.TS1800,
HistorySourcesRequestInterval = TimeSpan.FromSeconds(1),
EnableBackoff = false,
@@ -64,24 +70,17 @@ namespace Tango.Telemetry.Tester.IOT.CLI
}
}
- [TelemetryName("JobRun")]
- public class JobRunTestTelemetry : TelemetryBase
- {
- public String JobName { get; set; }
- public String Thread { get; set; }
- public double Length { get; set; }
- }
-
public class JobRunsTestSource : ITelemetryHistorySource
{
- private int counter = 1;
+ private bool _busy;
- public string Name { get; } = "Persons Source";
+ public string Name { get; } = "JobRuns Source";
public bool RequiresTelemetryDuplicationTracking { get; } = false;
+ public TelemetryHistorySourceDirection Direction { get => TelemetryHistorySourceDirection.Descending; }
public Task<bool> CanRequestHistory(DateTime from)
{
- return Task.FromResult(true);
+ return Task.FromResult(!_busy);
}
public void Dispose()
@@ -91,17 +90,24 @@ namespace Tango.Telemetry.Tester.IOT.CLI
public Task<IEnumerable<ITelemetry>> RequestHistory(DateTime from)
{
- return Task.
- FromResult<IEnumerable<ITelemetry>>(new List<JobRunTestTelemetry>()
- {
- new JobRunTestTelemetry()
- {
- Time = DateTime.UtcNow,
- JobName = $"Job For Materialized {counter++}",
- Length = 1000 + counter,
- Thread = $"Coats Thread {counter}"
- }
- });
+ _busy = true;
+
+ ObservablesContext.OverrideSettingsDataSource(new Core.DataSource()
+ {
+ Address = "localhost\\SQLPPC",
+ IntegratedSecurity = true,
+ Catalog = "Tango",
+ Type = Core.DataSourceType.SQLServer,
+ });
+
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ var runs = db.JobRuns.OrderByDescending(x => x.LastUpdated).Where(x => x.LastUpdated < from).Take(1).ToList();
+ var runsT = runs.Select(x => JobRunMapper.MapJobRun(x)).ToList();
+
+ _busy = false;
+ return Task.FromResult<IEnumerable<ITelemetry>>(runsT);
+ }
}
}
}
diff --git a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Tango.Telemetry.Tester.IOT.CLI.csproj b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Tango.Telemetry.Tester.IOT.CLI.csproj
index 0449a67fe..4b047b3dd 100644
--- a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Tango.Telemetry.Tester.IOT.CLI.csproj
+++ b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Tango.Telemetry.Tester.IOT.CLI.csproj
@@ -51,6 +51,12 @@
<Reference Include="DotNetty.Transport, Version=0.4.6.0, Culture=neutral, PublicKeyToken=bc13ca065fa06c29, processorArchitecture=MSIL">
<HintPath>..\..\packages\DotNetty.Transport.0.4.6\lib\net45\DotNetty.Transport.dll</HintPath>
</Reference>
+ <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
+ </Reference>
+ <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="Microsoft.Azure.Amqp, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Azure.Amqp.2.0.6\lib\net45\Microsoft.Azure.Amqp.dll</HintPath>
</Reference>
@@ -113,6 +119,7 @@
<HintPath>..\..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
+ <Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Console, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath>
</Reference>
@@ -193,6 +200,10 @@
<Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project>
<Name>Tango.Core</Name>
</ProjectReference>
+ <ProjectReference Include="..\..\Tango.Logging\Tango.Logging.csproj">
+ <Project>{BC932DBD-7CDB-488C-99E4-F02CF441F55E}</Project>
+ <Name>Tango.Logging</Name>
+ </ProjectReference>
<ProjectReference Include="..\..\Tango.Telemetry\Tango.Telemetry.csproj">
<Project>{af593663-d4e9-4a14-a3f2-fea57f30e9e6}</Project>
<Name>Tango.Telemetry</Name>
diff --git a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/packages.config b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/packages.config
index 8dabdb1c2..c64d28868 100644
--- a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/packages.config
+++ b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/packages.config
@@ -7,6 +7,7 @@
<package id="DotNetty.Handlers" version="0.4.6" targetFramework="net461" />
<package id="DotNetty.Transport" version="0.4.6" targetFramework="net461" />
<package id="EnterpriseLibrary.TransientFaultHandling" version="6.0.1304.0" targetFramework="net461" />
+ <package id="EntityFramework" version="6.2.0" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net461" />
<package id="Microsoft.Azure.Amqp" version="2.0.6" targetFramework="net461" />
<package id="Microsoft.Azure.Devices.Client" version="1.6.0" targetFramework="net461" />