diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2025-08-04 01:09:55 +0300 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2025-08-04 01:09:55 +0300 |
| commit | 8bbeffb422e8535c399f1eb76a55fdee5a1c65b6 (patch) | |
| tree | f200faa0e11c23f9105c3f12e0a6a2ea51832214 /Software/Visual_Studio | |
| parent | 0df9f37075dd697ac34f4ed2a2749f62aa27a654 (diff) | |
| download | Tango-8bbeffb422e8535c399f1eb76a55fdee5a1c65b6.tar.gz Tango-8bbeffb422e8535c399f1eb76a55fdee5a1c65b6.zip | |
Telemetry JobRuns.
Diffstat (limited to 'Software/Visual_Studio')
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" /> |
