ringbuffer and statistics
This commit is contained in:
14
VisionBuilder.UI.Statistics/ModuleExtensions.cs
Normal file
14
VisionBuilder.UI.Statistics/ModuleExtensions.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Ninject.Extensions.ChildKernel;
|
||||
using VisionBuilder.UI.Common;
|
||||
|
||||
namespace VisionBuilder.UI.Statistics;
|
||||
|
||||
public static class ModuleExtensions
|
||||
{
|
||||
public static IChildKernel UseStatistics(this IChildKernel self, string cameraName)
|
||||
{
|
||||
self.Bind<VisionBuilderStatisticsSettings, ISettings>().ToConstant(new VisionBuilderStatisticsSettings(cameraName));
|
||||
self.RegisterModule<VisionBuilderStatistics>();
|
||||
return self;
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,9 @@ using VisionBuilder.UI.Common.RecipeProcessing;
|
||||
|
||||
namespace VisionBuilder.UI.Statistics
|
||||
{
|
||||
public class VisionBuilderStatistics:IInitializable
|
||||
public class VisionBuilderStatistics:IVisionBuilderModule,IDisposable
|
||||
{
|
||||
private CsvStatistics _csvStatistics;
|
||||
private CsvStatistics? _csvStatistics;
|
||||
private readonly VisionBuilderStatisticsSettings _settings;
|
||||
private string _filePath;
|
||||
private readonly IRecognitionControl _recognitionControl;
|
||||
@@ -29,7 +29,7 @@ namespace VisionBuilder.UI.Statistics
|
||||
private const string MONTHLY_FILE_NAME = "statistics_month.csv";
|
||||
private const string EMPTY_DATE = "";
|
||||
private const string EMPTY_TIME = "";
|
||||
|
||||
public bool DoNotDeleteTempFiles { get; set; } = false;
|
||||
|
||||
public VisionBuilderStatistics(VisionBuilderStatisticsSettings settings, IRecognitionControl recognitionControl, ILoadingService loadingService)
|
||||
{
|
||||
@@ -37,18 +37,20 @@ namespace VisionBuilder.UI.Statistics
|
||||
_recognitionControl = recognitionControl;
|
||||
_loadingService = loadingService;
|
||||
|
||||
_recognitionControl.SessionStarted += _recognitionControl_SessionStarted;
|
||||
_recognitionControl.ImageProcessed += _recognitionControl_ImageProcessed;
|
||||
_recognitionControl.SessionEnded += _recognitionControl_SessionEnded;
|
||||
|
||||
}
|
||||
|
||||
private void _recognitionControl_SessionEnded(SessionEndedEvent obj)
|
||||
{
|
||||
var endedAt = obj.SessionEnded;
|
||||
_endTime = endedAt;
|
||||
_loadingService.StartLoading("Writing statistics for " + _settings.CameraName);
|
||||
try
|
||||
{
|
||||
_csvStatistics.WriteLine([_startTime.ToString("d"), _startTime.ToString("T"), DateTime.Now.ToString("d"), DateTime.Now.ToString("T"), "", "", ""]);
|
||||
_csvStatistics.WriteLine([_startTime.ToString("d"), _startTime.ToString("T"), endedAt.ToString("d"), endedAt.ToString("T"), "", "", ""]);
|
||||
_csvStatistics.Dispose();
|
||||
_csvStatistics = null;
|
||||
|
||||
WriteFinalStatistics();
|
||||
}
|
||||
finally
|
||||
@@ -67,10 +69,10 @@ namespace VisionBuilder.UI.Statistics
|
||||
|
||||
private void _recognitionControl_SessionStarted(SessionStartedEvent obj)
|
||||
{
|
||||
_startTime = DateTime.Now;
|
||||
_startTime = obj.SessionStarted;
|
||||
_currentRecipe = obj.RecipeName;
|
||||
_fileName = "tmp_"+Guid.NewGuid().ToString()+".csv";
|
||||
_directoryPath = PathSettingsUtils.ConvertVariables(_settings.PathTemplate, DateTime.Now, DateTime.Now,
|
||||
_directoryPath = PathSettingsUtils.ConvertVariables(_settings.PathTemplate, _startTime, _startTime,
|
||||
obj.RecipeName, cameraName: _settings.CameraName);
|
||||
_filePath = Path.Combine(_directoryPath, _fileName);
|
||||
var headers = new[] { _settings.StartDateColumnName, _settings.StartTimeColumnName, _settings.EndDateColumnName, _settings.EndTimeColumnName, _settings.ErrorTimeColumnName, _settings.ProductColumnName, _settings.ErrorColumnName };
|
||||
@@ -84,6 +86,8 @@ namespace VisionBuilder.UI.Statistics
|
||||
}
|
||||
|
||||
ConcurrentDictionary<string, int> _defects = new();
|
||||
private DateTime _endTime;
|
||||
|
||||
private void RecordBadImage(string defectName)
|
||||
{
|
||||
|
||||
@@ -96,50 +100,60 @@ namespace VisionBuilder.UI.Statistics
|
||||
_defects.AddOrUpdate(defectName, 1, (key, oldValue) => oldValue + 1);
|
||||
}
|
||||
|
||||
private void WriteMonthStatistics(string filename)
|
||||
private void WriteMonthStatistics()
|
||||
{
|
||||
// read second line to get the start time
|
||||
var lines = File.ReadAllLines(filename);
|
||||
var lastLine = lines[^1];
|
||||
if (lines.Length < 2) return; // no data to write
|
||||
var startDate = DateTime.Parse(lastLine.Split(',')[0]);
|
||||
var startTime = DateTime.Parse(lastLine.Split(',')[1]);
|
||||
var endDate = DateTime.Parse(lastLine.Split(',')[2]);
|
||||
var endTime = DateTime.Parse(lastLine.Split(',')[3]);
|
||||
|
||||
// all must be non-empty
|
||||
if (startDate == DateTime.MinValue || startTime == DateTime.MinValue || endDate == DateTime.MinValue || endTime == DateTime.MinValue)
|
||||
var startDate = _startTime.Date;
|
||||
var startTime = _startTime;
|
||||
var endDate = _endTime.Date;
|
||||
var endTime = _endTime;
|
||||
|
||||
var monthFilePath = Path.Combine(_directoryPath, MONTHLY_FILE_NAME);
|
||||
|
||||
var monthStatistics = new CsvStatistics(monthFilePath, [
|
||||
"Date start","Time start","Date end", "Time end" ,"Product","Error type","Error count"
|
||||
]);
|
||||
|
||||
foreach (var defect in _defects)
|
||||
{
|
||||
Log.Error("Invalid date or time in statistics file: " + filename);
|
||||
throw new InvalidOperationException("Invalid date or time in statistics file: " + filename);
|
||||
monthStatistics.WriteLine(
|
||||
[startDate.ToString("d"), startTime.ToString("T"), endDate.ToString("d"), endTime.ToString("T"), _currentRecipe, defect.Key, defect.Value.ToString()]
|
||||
);
|
||||
}
|
||||
|
||||
monthStatistics.Dispose();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void WriteFinalStatistics()
|
||||
{
|
||||
try
|
||||
{
|
||||
var tmpFiles = Directory.GetFiles(_directoryPath, "tmp_*");
|
||||
// order by creation time
|
||||
Array.Sort(tmpFiles, (x, y) => File.GetCreationTime(x).CompareTo(File.GetCreationTime(y)));
|
||||
foreach (var file in tmpFiles)
|
||||
{
|
||||
var finalFileName = Path.Combine(_directoryPath, BY_EVENTS_FILE_NAME);
|
||||
var lines = File.ReadAllLines(file);
|
||||
File.AppendAllLines(finalFileName, lines.Skip(1)); // skip header
|
||||
WriteMonthStatistics(file);
|
||||
File.Delete(file);
|
||||
}
|
||||
Log.Debug("Writing month statistics");
|
||||
WriteMonthStatistics();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Error writing statistics for " + _settings.CameraName+ e);
|
||||
Log.Error("Error writing statistics for " + _settings.CameraName+ "\n"+ e);
|
||||
}
|
||||
_csvStatistics?.Dispose();
|
||||
_csvStatistics = null;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
public void InitializeModule()
|
||||
{
|
||||
WriteFinalStatistics();
|
||||
_recognitionControl.SessionStarted += _recognitionControl_SessionStarted;
|
||||
_recognitionControl.ImageProcessed += _recognitionControl_ImageProcessed;
|
||||
_recognitionControl.SessionEnded += _recognitionControl_SessionEnded;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_csvStatistics?.Dispose();
|
||||
_recognitionControl.SessionStarted -= _recognitionControl_SessionStarted;
|
||||
_recognitionControl.ImageProcessed -= _recognitionControl_ImageProcessed;
|
||||
_recognitionControl.SessionEnded -= _recognitionControl_SessionEnded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Inspectron.Settings;
|
||||
using Inspectron.Settings.Attributes;
|
||||
using Lindt.Colorballs.Duo.Utils;
|
||||
using VisionBuilder.UI.Common;
|
||||
|
||||
namespace VisionBuilder.UI.Statistics;
|
||||
@@ -16,31 +17,10 @@ public class VisionBuilderStatisticsSettings: ISettings
|
||||
[SettingDescription(
|
||||
@"
|
||||
Specifies directory, in which MaxBad and MaxGood are applied.
|
||||
You can use the following system variables:
|
||||
|
||||
$RECIPE_NAME - name of the current recipe
|
||||
$DEFECT_NAME - name of the current defect(for bad images)
|
||||
$CAMERA_NAME - name of the camera
|
||||
|
||||
$HOUR - hour of the image
|
||||
$MINUTE - minute of the image
|
||||
$SECOND - second of the image
|
||||
$MS - milliseconds of the image
|
||||
|
||||
$DAY - day of the image
|
||||
$MONTH - month of the image
|
||||
$YEAR - year of the image
|
||||
|
||||
$SS_HOUR - hour of the session start
|
||||
$SS_MINUTE - minute of the session start
|
||||
$SS_SECOND - second of the session start
|
||||
|
||||
$SS_DAY - day of the session start
|
||||
$SS_MONTH - month of the session start
|
||||
$SS_YEAR - year of the session start
|
||||
"
|
||||
"+PathSettingsUtils.INSTUCTIONS
|
||||
)]
|
||||
public string PathTemplate { get; set; }= @$"..\Data\Statistics\$SS_MONTH $SS_YEAR\$RECIPE_NAME\";
|
||||
[SettingPreview(typeof(VisionBuilderStatisticsSettings), nameof(PathTemplatePreview))]
|
||||
public string PathTemplate { get; set; }= @$"..\Data\Statistics\$SS_MONTH_NUM $SS_YEAR\$RECIPE_NAME\";
|
||||
|
||||
public string StartDateColumnName { get; set; } = "Start Date";
|
||||
public string StartTimeColumnName { get; set; } = "Start time";
|
||||
@@ -61,4 +41,10 @@ $SS_YEAR - year of the session start
|
||||
settings.RegisterSimple(this,()=>this.ProductColumnName,CameraName+"/"+"Statistics",nameof(ProductColumnName));
|
||||
settings.RegisterSimple(this,()=>this.ErrorColumnName,CameraName+"/"+"Statistics",nameof(ErrorColumnName));
|
||||
}
|
||||
|
||||
public static string PathTemplatePreview(object template)
|
||||
{
|
||||
return PathSettingsUtils.ConvertVariables((string)template, DateTime.Now, DateTime.Now, "my recipe",
|
||||
"my defect", "my camera");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user