diff --git a/GSS2.Test/App.axaml b/GSS2.Test/App.axaml
deleted file mode 100644
index 42975d7..0000000
--- a/GSS2.Test/App.axaml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/GSS2.Test/App.axaml.cs b/GSS2.Test/App.axaml.cs
deleted file mode 100644
index 257f466..0000000
--- a/GSS2.Test/App.axaml.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using Avalonia;
-using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Markup.Xaml;
-using Avalonia.Threading;
-
-using GSS2.Test.ViewModels;
-using GSS2.Test.Views;
-using GSS2.UI.Core;
-using GSS2.UI.Core.Services;
-using GSS2.UI.Core.ViewModels;
-
-namespace GSS2.Test;
-
-public partial class App : Application
-{
- public override void Initialize()
- {
- AvaloniaXamlLoader.Load(this);
- }
-
- public override void OnFrameworkInitializationCompleted()
- {
- if (ApplicationLifetime is null)
- throw new InvalidOperationException("Application framework initialization cannot be fulfilled, ApplicationLifetime is null");
-
- var loggerFactory = Program.ApplicationHost.Services.GetRequiredService();
- var navigationService = Program.ApplicationHost.Services.GetRequiredService();
-
- switch (ApplicationLifetime)
- {
- case IClassicDesktopStyleApplicationLifetime desktop:
- Console.WriteLine("Application running in classic style");
- Console.WriteLine($"Application running in {(Program.IsFullscreen ? "fullscreen" : "window")} mode");
-
- desktop.Startup += (_, _) => Program.ApplicationHost.RunAsync();
- desktop.Exit += (_, _) => Program.ApplicationHost.StopAsync();
-
- var mainWindowViewModelLogger = loggerFactory.CreateLogger();
- var mainWindow = new MainWindow()
- {
- DataContext = new MainWindowViewModel(mainWindowViewModelLogger)
- {
- SystemDecorations = Program.IsFullscreen ? Avalonia.Controls.SystemDecorations.None : Avalonia.Controls.SystemDecorations.Full,
- Topmost = Program.IsFullscreen,
- WindowState = Program.IsFullscreen ? Avalonia.Controls.WindowState.FullScreen : Avalonia.Controls.WindowState.Normal
- },
- };
- desktop.MainWindow = mainWindow;
-
- Program.ShutdownRequested += (_, _) => Dispatcher.UIThread.Invoke(() => desktop.MainWindow?.Close());
- break;
-
- case ISingleViewApplicationLifetime singleView:
- Console.WriteLine("Application running in single view style");
- break;
-
- default:
- throw new InvalidOperationException($"Application framework initialization cannot be fulfilled, ApplicationLifetime has unknown type inherited from: {string.Join(", ", ApplicationLifetime.GetType().GetInterfaces().Select(i => i.FullName))}");
-
- }
-
- var mainViewLogger = loggerFactory.CreateLogger();
- var mainView = new MainView(mainViewLogger)
- {
- DataContext = Program.ApplicationHost.Services.GetRequiredService()
- };
- navigationService.NavigateTo(mainView);
-
- base.OnFrameworkInitializationCompleted();
- }
-
-}
\ No newline at end of file
diff --git a/GSS2.Test/DependencyInjectionHelper.cs b/GSS2.Test/DependencyInjectionHelper.cs
deleted file mode 100644
index 4ec6570..0000000
--- a/GSS2.Test/DependencyInjectionHelper.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using GSS2.UI.Core.Views;
-using GSS2.UI.Core.ViewModels;
-using GSS2.Test.Views;
-using GSS2.Test.ViewModels;
-using GSS2.UI.Core.Services;
-
-using Avalonia;
-
-namespace GSS2.Test;
-
-public static class DependencyInjectionHelper
-{
- public static IServiceCollection AddViewsAndModels(this IServiceCollection services) =>
- services
- .AddSingleton((_) => new NavigationService(Application.Current?.ApplicationLifetime))
- .AddSingleton()
- .AddSingleton()
- .AddSingleton()
- .AddSingleton()
- .AddSingleton()
- .AddSingleton()
- .AddSingleton()
- .AddSingleton()
- .AddSingleton();
-}
\ No newline at end of file
diff --git a/GSS2.Test/DependencyInjectionViewLocator.cs b/GSS2.Test/DependencyInjectionViewLocator.cs
deleted file mode 100644
index 5e72dab..0000000
--- a/GSS2.Test/DependencyInjectionViewLocator.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Controls.Templates;
-
-using GSS2.UI.Core.ViewModels;
-
-namespace GSS2.Test;
-
-public class DependencyInjectionViewLocator : IDataTemplate
-{
- public Control? Build(object? data)
- {
- if (data is null)
- return null;
-
- var name = data.GetType().AssemblyQualifiedName?
- .Replace("ViewModels", "Views")
- .Replace("ViewModel", "View");
- if (name is null)
- return new TextBlock { Text = $"Not found: {data}" };
- var type = Type.GetType(name);
- if (type is null)
- return new TextBlock { Text = $"Not found type: {name} for {data}" };
-
- var control = Program.ApplicationHost.Services.GetRequiredService(type) as Control;
- if (control is null)
- return new TextBlock { Text = $"Not found in DI: {type} for {data}" };
-
- control.DataContext = data;
- return control;
- }
-
- public bool Match(object? data) => data is ViewModelBase;
-}
\ No newline at end of file
diff --git a/GSS2.Test/GSS2.Test.csproj b/GSS2.Test/GSS2.Test.csproj
deleted file mode 100644
index 0fc87b7..0000000
--- a/GSS2.Test/GSS2.Test.csproj
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
- WinExe
- net10.0
- enable
- enable
- dotnet-GSS2.Test-191ece0a-855d-46ec-9ecb-44378fc3db83
- app.manifest
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/GSS2.Test/Program.cs b/GSS2.Test/Program.cs
deleted file mode 100644
index bc1bc11..0000000
--- a/GSS2.Test/Program.cs
+++ /dev/null
@@ -1,189 +0,0 @@
-using Avalonia;
-using Avalonia.OpenGL.Egl;
-
-using System.CommandLine;
-
-namespace GSS2.Test;
-
-public partial class Program
-{
- private enum RenderingMode
- {
- X11,
- DRM
- }
-
- private static List? _args = null;
- private static readonly RootCommand _rootCommand = new("Run UI application");
- private static readonly Option _fullscreen = new("--fullscreen")
- {
- Description = "Run in fullscreen mode"
- };
- private static readonly Option _renderingMode = new("--rendering-mode")
- {
- Description = "Rendering mode to use",
- DefaultValueFactory = (_) => RenderingMode.X11
- };
- private static readonly Option _hideConsole = new("--hide-console")
- {
- Description = "Suppress console output",
- DefaultValueFactory = (result) => result.GetRequiredValue(_renderingMode) == RenderingMode.DRM
- };
-
- private static readonly Command _cameraTuningCommand = new("camera-tuning")
- {
- Description = "Tune camera parameters"
- };
- private static readonly Option _cameraTuningOutputFile = new("--output")
- {
- Description = "Output image file",
- Required = false
- };
- private static readonly Option _cameraTuningGainR = new("--gain-r")
- {
- Description = "Color gain (red channel) to start from",
- DefaultValueFactory = (_) => 1
- };
- private static readonly Option _cameraTuningGainG = new("--gain-g")
- {
- Description = "Color gain (green channel) to start from",
- DefaultValueFactory = (_) => 1
- };
- private static readonly Option _cameraTuningGainB = new("--gain-b")
- {
- Description = "Color gain (blue channel) to start from",
- DefaultValueFactory = (_) => 1
- };
- private static readonly Option _cameraTuningThreshold = new("--threshold")
- {
- Description = "Threshold to stop on",
- DefaultValueFactory = (_) => 0.1
- };
- private static readonly Option _cameraTuningSteps = new("--steps")
- {
- Description = "Maximum steps count",
- DefaultValueFactory = (_) => 10
- };
-
- private static readonly Command _captureCommand = new("capture")
- {
- Description = "Capture image from camera"
- };
- private static readonly Option _captureOutputFile = new("--output")
- {
- Description = "Output image file",
- DefaultValueFactory = (_) => new FileInfo("image.png")
- };
- private static readonly Option _captureIntensityWhite = new("--intensity-white")
- {
- Description = "Illuminator intensity for white (from 0 to 1)",
- DefaultValueFactory = (_) => 1
- };
- private static readonly Option _captureIntensityUv365nm = new("--intensity-uv365nm")
- {
- Description = "Illuminator intensity for UV 365 nm (from 0 to 1)",
- DefaultValueFactory = (_) => 0
- };
- private static readonly Option _captureIntensityUv254nm = new("--intensity-uv254nm")
- {
- Description = "Illuminator intensity for UV 254 nm (from 0 to 1)",
- DefaultValueFactory = (_) => 0
- };
-
- private static readonly Command _imageStorageClear = new("image-storage-clear")
- {
- Description = "Clear image storage from unused images"
- };
-
-
- public static event ConsoleCancelEventHandler? ShutdownRequested;
-
- [STAThread]
- public static int Main(string[] args)
- {
- _args = args.ToList();
-
-#if DEBUG
- WaitDebuggerIfNeeded();
-#endif
-
- _rootCommand.SetAction(Ui);
- _rootCommand.Add(_fullscreen);
- _rootCommand.Add(_renderingMode);
- _rootCommand.Add(_hideConsole);
-
- _rootCommand.Add(_cameraTuningCommand);
- _cameraTuningCommand.SetAction(CameraTuning);
- _cameraTuningCommand.Add(_cameraTuningOutputFile);
- _cameraTuningCommand.Add(_cameraTuningGainR);
- _cameraTuningCommand.Add(_cameraTuningGainG);
- _cameraTuningCommand.Add(_cameraTuningGainB);
- _cameraTuningCommand.Add(_cameraTuningThreshold);
- _cameraTuningCommand.Add(_cameraTuningSteps);
-
- _rootCommand.Add(_captureCommand);
- _captureCommand.SetAction(Capture);
- _captureCommand.Add(_captureOutputFile);
- _captureCommand.Add(_captureIntensityWhite);
- _captureCommand.Add(_captureIntensityUv365nm);
- _captureCommand.Add(_captureIntensityUv254nm);
-
- _rootCommand.Add(_imageStorageClear);
- _imageStorageClear.SetAction(ImageStorageClear);
-
- Console.CancelKeyPress += new ConsoleCancelEventHandler(OnProgramShutdown);
- Console.WriteLine("Press Ctrl+C to shut down.");
-
- var parseResult = _rootCommand.Parse(_args);
- if (parseResult.Errors.Count() != 0)
- {
- foreach (var parseError in parseResult.Errors)
- Console.Error.WriteLine(parseError.Message);
- return 1;
- }
-
- return parseResult.Invoke();
- }
-
- private static void OnProgramShutdown(object? sender, ConsoleCancelEventArgs ea)
- {
- ShutdownRequested?.Invoke(sender, ea);
- ea.Cancel = true;
- }
-
- private static void WaitDebuggerIfNeeded()
- {
- if (System.Diagnostics.Debugger.IsAttached)
- return;
-
- if (_args is null || !_args.Contains("--debug"))
- return;
-
- _args.Remove("--debug");
-
- bool keepWaiting = true;
-
- void CancelHandle(object? sender, ConsoleCancelEventArgs e)
- {
- e.Cancel = true;
- keepWaiting = false;
- Console.WriteLine("\nWait cancelled by user.");
- Environment.Exit(0);
- }
- Console.CancelKeyPress += CancelHandle;
-
- Console.WriteLine("Waiting debugger attach (Press Ctrl+C to cancel)");
- Console.WriteLine($"Process Id: {Environment.ProcessId}");
- Console.WriteLine($"Process Name: {Environment.ProcessPath}");
- Console.WriteLine($"Thread Id: {Thread.CurrentThread.ManagedThreadId}");
- Console.WriteLine($"Thread Name: {Thread.CurrentThread.Name}");
-
- while (!System.Diagnostics.Debugger.IsAttached && keepWaiting)
- Thread.Sleep(100);
-
- if (System.Diagnostics.Debugger.IsAttached)
- System.Diagnostics.Debugger.Break();
-
- Console.CancelKeyPress -= CancelHandle;
- }
-}
diff --git a/GSS2.Test/ProgramCameraTuning.cs b/GSS2.Test/ProgramCameraTuning.cs
deleted file mode 100644
index a4c1439..0000000
--- a/GSS2.Test/ProgramCameraTuning.cs
+++ /dev/null
@@ -1,330 +0,0 @@
-using System.CommandLine;
-
-using GSS2.Core;
-using GSS2.Core.Hardware;
-using GSS2.Core.Logging;
-
-using Microsoft.Extensions.Logging.Console;
-
-using OpenCvSharp;
-
-using ConsoleFormatter = GSS2.Core.Logging.ConsoleFormatter;
-
-namespace GSS2.Test;
-
-public partial class Program
-{
- private class CameraTuningWorker : BackgroundService
- {
- private readonly ILogger _logger;
- private readonly IHostApplicationLifetime _applicationLifetime;
- private readonly CameraService _cameraService;
- private readonly IlluminatorService _illuminatorService;
- private readonly FileInfo? _outputFile;
- private double _gainR;
- private double _gainG;
- private double _gainB;
- private readonly double _threshold;
- private readonly uint _steps;
- private static readonly Scalar[] KnownSegments =
- {
- new Scalar(0,255,255), // Cyan
- new Scalar(0,0,255), // Blue
- new Scalar(255,0,255), // Magenta
- new Scalar(128,128,128), // Gray (skip)
- new Scalar(255,0,0), // Red
- new Scalar(255,128,0), // Orange
- new Scalar(255,255,0), // Yellow
- new Scalar(0,255,0) // Green
- };
- private const double PatternOuterRadius = 180.0;
- private const double PatternCenterRadius = 60.0;
-
- public CameraTuningWorker(ILogger logger, IHostApplicationLifetime applicationLifetime, CameraService cameraService, IlluminatorService illuminatorService, FileInfo? outputFile, double gainR, double gainG, double gainB, double threshold, uint steps)
- {
- _applicationLifetime = applicationLifetime;
- _logger = logger;
- _cameraService = cameraService;
- _illuminatorService = illuminatorService;
- _outputFile = outputFile;
- _gainR = gainR;
- _gainG = gainG;
- _gainB = gainB;
- _threshold = threshold;
- _steps = steps;
- _logger.LogInformation("Initialized");
- _logger.LogInformation("Output File: {}", _outputFile);
- _logger.LogInformation("Gain R: {}", _gainR);
- _logger.LogInformation("Gain G: {}", _gainG);
- _logger.LogInformation("Gain B: {}", _gainB);
- _logger.LogInformation("Threshold: {}", _threshold);
- _logger.LogInformation("Steps: {}", _steps);
- }
-
- protected override async Task ExecuteAsync(CancellationToken stoppingToken)
- {
- _logger.LogInformation("Running camera fine tuning");
-
- Mat? image;
-
- int i = 0;
- bool optimalGainsFound = false;
-
- _illuminatorService.SetIntensity(1, 0, 0);
- _illuminatorService.TurnOn();
-
- while (i < _steps)
- {
- _cameraService.Configuration.DecodeGainR = _gainR;
- _cameraService.Configuration.DecodeGainG = _gainG;
- _cameraService.Configuration.DecodeGainB = _gainB;
-
- try
- {
- image = await _cameraService.CaptureImage(stoppingToken, 2);
-
- if (image is null)
- {
- _logger.LogError("Cannot get image");
- break;
- }
-
- if (image.Type() != MatType.CV_8UC3 &&
- image.Type() != MatType.CV_8UC4 &&
- image.Type() != MatType.CV_16UC3 &&
- image.Type() != MatType.CV_16UC4)
- {
- _logger.LogCritical("Unsupported image type: {}", image.Type().ToString());
- break;
- }
-
- if (image.Type() == MatType.CV_16UC3)
- image.ConvertTo(image, MatType.CV_8UC3, 1 / 256.0);
- if (image.Type() == MatType.CV_16UC4)
- image.ConvertTo(image, MatType.CV_8UC4, 1 / 256.0);
-
- var channels = image.Split();
- Cv2.Merge([channels[0], channels[1], channels[2]], image);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Exception occurred while image capturing");
- break;
- }
-
- try
- {
- if (_outputFile is not null)
- image.ImWrite(_outputFile.FullName);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Exception occurred while image saving");
- }
-
- try
- {
- var gains = ComputeWhiteBalanceGains(image);
- if (gains is null)
- {
- _logger.LogError("Cannot compute gains");
- break;
- }
-
- var (r, g, b) = gains.Value;
- if (Math.Abs(_gainR - r) < _threshold &&
- Math.Abs(_gainG - g) < _threshold &&
- Math.Abs(_gainB - b) < _threshold)
- {
- _logger.LogInformation("Optimal color gains: r={}, g={}, b:={}", r, g, b);
- optimalGainsFound = true;
- break;
- }
- _gainR = (_gainR + r) / 2;
- _gainG = (_gainG + g) / 2;
- _gainB = (_gainB + b) / 2;
- _logger.LogInformation("Step {}/{} color gains: r={}, g={}, b:={}", i + 1, _steps, _gainR, _gainG, _gainB);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Exception occurred while gains computing");
- break;
- }
- i++;
- }
- _illuminatorService.TurnOff();
-
- if (!optimalGainsFound)
- _logger.LogWarning("Optimal gains not found");
-
- _applicationLifetime.StopApplication();
- }
-
- private (double rGain, double gGain, double bGain)? ComputeWhiteBalanceGains(Mat image)
- {
- var circle = FindCircle(image);
- if (circle == null)
- return null;
-
- var (rx, ry, rr) = circle.Value;
-
- double scale = rr / PatternOuterRadius;
- double innerPx = PatternCenterRadius * scale;
- int midR = (int)((innerPx + rr) / 2.0);
-
- double phi0 = DetectOrientation(image, rx, ry, rr);
- if (double.IsNaN(phi0))
- phi0 = Math.PI / 2.0;
-
- var samples = new List();
- var refs = new List();
-
- int N = KnownSegments.Length;
-
- for (int i = 0; i < N; i++)
- {
- if (i == 3) continue; // skip gray
-
- double theta = phi0 - (2 * Math.PI / N) * i;
-
- int cx = (int)(rx + midR * Math.Cos(theta));
- int cy = (int)(ry - midR * Math.Sin(theta));
-
- var roi = new Rect(
- Math.Max(cx - 8, 0),
- Math.Max(cy - 8, 0),
- Math.Min(16, image.Width - Math.Max(cx - 8, 0)),
- Math.Min(16, image.Height - Math.Max(cy - 8, 0)));
-
- if (roi.Width < 8 || roi.Height < 8)
- continue;
-
- using var patch = new Mat(image, roi);
- var mean = Cv2.Mean(patch);
-
- // BGR → RGB
- samples.Add(new Vec3d(mean.Val2, mean.Val1, mean.Val0));
-
- var refColor = KnownSegments[i];
- refs.Add(new Vec3d(refColor.Val2, refColor.Val1, refColor.Val0));
- }
-
- if (samples.Count < 3)
- return null;
-
- // Формируем матрицы для least squares
- var S = new Mat(samples.Count, 3, MatType.CV_64F);
- var R = new Mat(samples.Count, 3, MatType.CV_64F);
-
- for (int i = 0; i < samples.Count; i++)
- {
- S.Set(i, 0, samples[i][0]);
- S.Set(i, 1, samples[i][1]);
- S.Set(i, 2, samples[i][2]);
-
- R.Set(i, 0, refs[i][0]);
- R.Set(i, 1, refs[i][1]);
- R.Set(i, 2, refs[i][2]);
- }
-
- var M = new Mat();
- Cv2.Solve(S, R, M, DecompTypes.Normal);
-
- double rGain = Math.Max(M.At(0, 0), 1.0);
- double gGain = 1.0;
- double bGain = Math.Max(M.At(2, 2), 1.0);
-
- return (rGain, gGain, bGain);
- }
- private (int x, int y, int r)? FindCircle(Mat image)
- {
- using var gray = new Mat();
- Cv2.CvtColor(image, gray, ColorConversionCodes.BGR2GRAY);
- Cv2.GaussianBlur(gray, gray, new Size(9, 9), 2);
-
- var circles = Cv2.HoughCircles(
- gray,
- HoughModes.Gradient,
- dp: 1.2,
- minDist: gray.Rows / 3,
- param1: 100,
- param2: 30,
- minRadius: (int)(gray.Rows * 0.3),
- maxRadius: (int)(gray.Rows * 0.6));
-
- if (circles.Length == 0)
- return null;
-
- var c = circles[0];
- return ((int)c.Center.X, (int)c.Center.Y, (int)c.Radius);
- }
- private double DetectOrientation(Mat image, int rx, int ry, int rr)
- {
- double scale = rr / PatternOuterRadius;
- int innerR = (int)(PatternCenterRadius * scale);
-
- using var gray = new Mat();
- Cv2.CvtColor(image, gray, ColorConversionCodes.BGR2GRAY);
-
- using var mask = Mat.Zeros(image.Size(), MatType.CV_8U).ToMat();
- Cv2.Circle(mask, new Point(rx, ry), innerR, Scalar.White, -1);
-
- var whitePoints = new List();
-
- for (int y = 0; y < gray.Rows; y++)
- {
- for (int x = 0; x < gray.Cols; x++)
- {
- if (mask.At(y, x) == 255 &&
- gray.At(y, x) > 128)
- {
- whitePoints.Add(new Point(x, y));
- }
- }
- }
-
- if (whitePoints.Count < 20)
- return double.NaN;
-
- double cx = whitePoints.Average(p => p.X);
- double cy = whitePoints.Average(p => p.Y);
-
- return Math.Atan2(ry - cy, cx - rx);
- }
- }
- private static void CameraTuning(ParseResult parseResult)
- {
- var outputFile = parseResult.GetValue(_cameraTuningOutputFile);
- var gainR = parseResult.GetRequiredValue(_cameraTuningGainR);
- var gainG = parseResult.GetRequiredValue(_cameraTuningGainG);
- var gainB = parseResult.GetRequiredValue(_cameraTuningGainB);
- var threshold = parseResult.GetRequiredValue(_cameraTuningThreshold);
- var steps = parseResult.GetRequiredValue(_cameraTuningSteps);
-
- var builder = Host.CreateApplicationBuilder();
-
- builder.Logging.ClearProviders();
- builder.Logging.AddConsole(options => options.FormatterName = nameof(ConsoleFormatter));
- builder.Logging.AddConsoleFormatter();
- builder.Logging.AddProvider(new FileLoggerProvider("full.log", true));
- builder.Logging.AddProvider(new FileLoggerProvider("last_run.log", false));
- builder.Services.AddSingleton();
-
- builder.Services.AddIlluminatorService("Hardware:Illuminator");
- builder.Services.AddCameraService("Hardware:Camera", true);
-
- builder.Services.AddHostedService(services =>
- {
- var logger = services.GetRequiredService>();
- var applicationLifetime = services.GetRequiredService();
- var cameraService = services.GetRequiredService();
- var illuminatorService = services.GetRequiredService();
- return new CameraTuningWorker(logger, applicationLifetime, cameraService, illuminatorService, outputFile, gainB, gainG, gainR, threshold, steps);
- });
-
- var host = builder.Build();
- host.Services.GetRequiredService();
-
- host.Run();
- }
-}
diff --git a/GSS2.Test/ProgramCapture.cs b/GSS2.Test/ProgramCapture.cs
deleted file mode 100644
index f8460c1..0000000
--- a/GSS2.Test/ProgramCapture.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-using System.CommandLine;
-
-using GSS2.Core;
-using GSS2.Core.Hardware;
-using GSS2.Core.Logging;
-
-using Microsoft.Extensions.Logging.Console;
-
-using OpenCvSharp;
-
-using ConsoleFormatter = GSS2.Core.Logging.ConsoleFormatter;
-
-namespace GSS2.Test;
-
-public partial class Program
-{
- private class CaptureWorker : BackgroundService
- {
- private readonly ILogger _logger;
- private readonly IHostApplicationLifetime _applicationLifetime;
- private readonly CameraService _cameraService;
- private readonly IlluminatorService _illuminatorService;
- private readonly FileInfo _outputFile;
- private readonly double _intensityWhite;
- private readonly double _intensityUv365nm;
- private readonly double _intensityUv254nm;
-
- public CaptureWorker(ILogger logger, IHostApplicationLifetime applicationLifetime, CameraService cameraService, IlluminatorService illuminatorService, FileInfo outputFile, double intensityWhite, double intensityUv365nm, double intensityUv254nm)
- {
- _applicationLifetime = applicationLifetime;
- _logger = logger;
- _cameraService = cameraService;
- _illuminatorService = illuminatorService;
- _outputFile = outputFile;
- _intensityWhite = intensityWhite;
- _intensityUv365nm = intensityUv365nm;
- _intensityUv254nm = intensityUv254nm;
-
- _logger.LogInformation("Initialized");
- _logger.LogInformation("Output File: {}", _outputFile);
- _logger.LogInformation("Intensity White: {}", _intensityWhite);
- _logger.LogInformation("Intensity UV 365 nm: {}", _intensityUv365nm);
- _logger.LogInformation("Intensity UV 254 nm: {}", _intensityUv254nm);
- }
-
- protected override async Task ExecuteAsync(CancellationToken stoppingToken)
- {
- _logger.LogInformation("Running camera fine tuning");
- _illuminatorService.SetIntensity(_intensityWhite, _intensityUv365nm, _intensityUv254nm);
- _illuminatorService.TurnOn();
-
- Mat? image;
- try
- {
- image = await _cameraService.CaptureImage(stoppingToken, 5);
-
- if (image is null)
- {
- _logger.LogCritical("Cannot get image");
- _applicationLifetime.StopApplication();
- return;
- }
- }
- catch (Exception ex)
- {
- _logger.LogCritical(ex, "Exception occurred while image capturing");
- _applicationLifetime.StopApplication();
- return;
- }
- finally
- {
- _illuminatorService.TurnOff();
- }
-
- try
- {
- image.ImWrite(_outputFile.FullName);
- _logger.LogInformation("Image saved: {}", _outputFile.FullName);
- }
- catch (Exception ex)
- {
- _logger.LogCritical(ex, "Exception occurred while image saving");
- }
-
- _applicationLifetime.StopApplication();
- }
-
- }
- private static void Capture(ParseResult parseResult)
- {
- var outputFile = parseResult.GetRequiredValue(_captureOutputFile);
- var intensityWhite = parseResult.GetRequiredValue(_captureIntensityWhite);
- var intensityUv365nm = parseResult.GetRequiredValue(_captureIntensityUv365nm);
- var intensityUv254nm = parseResult.GetRequiredValue(_captureIntensityUv254nm);
-
- var builder = Host.CreateApplicationBuilder();
-
- builder.Logging.ClearProviders();
- builder.Logging.AddConsole(options => options.FormatterName = nameof(ConsoleFormatter));
- builder.Logging.AddConsoleFormatter();
- builder.Logging.AddProvider(new FileLoggerProvider("full.log", true));
- builder.Logging.AddProvider(new FileLoggerProvider("last_run.log", false));
- builder.Services.AddSingleton();
-
- builder.Services.AddIlluminatorService("Hardware:Illuminator");
- builder.Services.AddCameraService("Hardware:Camera", true);
-
- builder.Services.AddHostedService(services =>
- {
- var logger = services.GetRequiredService>();
- var applicationLifetime = services.GetRequiredService();
- var cameraService = services.GetRequiredService();
- var illuminatorService = services.GetRequiredService();
- return new CaptureWorker(logger, applicationLifetime, cameraService, illuminatorService, outputFile, intensityWhite, intensityUv365nm, intensityUv254nm);
- });
-
- var host = builder.Build();
- host.Services.GetRequiredService();
-
- host.Run();
- }
-}
diff --git a/GSS2.Test/ProgramImagesStorageClear.cs b/GSS2.Test/ProgramImagesStorageClear.cs
deleted file mode 100644
index a453941..0000000
--- a/GSS2.Test/ProgramImagesStorageClear.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-using System.CommandLine;
-
-using GSS2.Core;
-using GSS2.Core.Analysis.AmineContent.Database.Calibration;
-using GSS2.Core.Hardware;
-using GSS2.Core.Logging;
-
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Logging.Console;
-
-using OpenCvSharp;
-
-using ConsoleFormatter = GSS2.Core.Logging.ConsoleFormatter;
-
-namespace GSS2.Test;
-
-public partial class Program
-{
- private class ImagesStorageClearWorker : BackgroundService
- {
- private readonly ILogger _logger;
- private readonly IHostApplicationLifetime _applicationLifetime;
- private readonly AmineContentCalibrationContext _context;
- private readonly ImageStorageService _imageStorageService;
-
- public ImagesStorageClearWorker(ILogger logger, IHostApplicationLifetime applicationLifetime, AmineContentCalibrationContext context, ImageStorageService imageStorageService)
- {
- _logger = logger;
- _applicationLifetime = applicationLifetime;
- _context = context;
- _imageStorageService = imageStorageService;
-
- _logger.LogInformation("Initialized");
- }
-
- protected override async Task ExecuteAsync(CancellationToken stoppingToken)
- {
- _logger.LogInformation("Running images storage clear");
-
- var recordsFiles = _context.ImageRecords.Select(r => r.ImagePath);
- var storedFiles = _imageStorageService.ListFiles()
- .Select(Path.GetFileName)
- .OfType();
-
- var unusedFiles = storedFiles.Except(recordsFiles)
- .ToList()
- .Order();
-
- if (unusedFiles is null || unusedFiles.Count() == 0)
- {
- _logger.LogInformation("Unused images not found");
- _applicationLifetime.StopApplication();
- return;
- }
-
- _logger.LogInformation("Found {} unused image(s):\n\t{}", unusedFiles.Count(), string.Join("\n\t", unusedFiles));
-
- while (!stoppingToken.IsCancellationRequested)
- {
- _logger.LogInformation("Delete this files? (y/n) ");
- var input = Console.ReadLine()?.Trim();
- if (input == "y")
- {
- foreach (var file in unusedFiles)
- _imageStorageService.Delete(file);
- break;
- }
- if (input == "n")
- break;
- }
-
- _applicationLifetime.StopApplication();
- }
-
- }
- private static void ImageStorageClear(ParseResult parseResult)
- {
- var builder = Host.CreateApplicationBuilder();
-
- builder.Logging.ClearProviders();
- builder.Logging.AddConsole(options => options.FormatterName = nameof(ConsoleFormatter));
- builder.Logging.AddConsoleFormatter();
- builder.Logging.AddProvider(new FileLoggerProvider("full.log", true));
- builder.Logging.AddProvider(new FileLoggerProvider("last_run.log", false));
- builder.Services.AddSingleton();
-
- builder.Services.AddAmineContentCalibrationContext(builder.Configuration);
- builder.Services.AddImageStorageService(new DirectoryInfo("images"));
-
- builder.Services.AddHostedService();
-
- var host = builder.Build();
-
- using (var scope = host.Services.CreateScope())
- {
- var context = scope.ServiceProvider.GetRequiredService();
- context.Database.Migrate();
- }
-
- host.Run();
- }
-}
diff --git a/GSS2.Test/PropgramUi.cs b/GSS2.Test/PropgramUi.cs
deleted file mode 100644
index b8d01eb..0000000
--- a/GSS2.Test/PropgramUi.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-using System.CommandLine;
-
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Logging.Console;
-
-using Avalonia;
-using Avalonia.OpenGL.Egl;
-
-using GSS2.Core;
-using GSS2.Core.Logging;
-using GSS2.Core.Analysis.AmineContent.Database.Calibration;
-using GSS2.Core.Analysis.AmineContent.Database.Results;
-
-using ConsoleFormatter = GSS2.Core.Logging.ConsoleFormatter;
-
-namespace GSS2.Test;
-
-public partial class Program
-{
- public static IHost ApplicationHost { get; } = BuildHostApp();
- public static bool IsFullscreen = false;
-
- private static void Ui(ParseResult parseResult)
- {
- var builder = BuildAvaloniaApp();
- var fullscreen = parseResult.GetValue(_fullscreen);
- var renderingMode = parseResult.GetValue(_renderingMode);
- var hideConsole = parseResult.GetValue(_hideConsole);
-
- IsFullscreen = fullscreen;
-
- if (hideConsole)
- SilenceConsole();
-
- switch (renderingMode)
- {
- case RenderingMode.X11:
- builder.StartWithClassicDesktopLifetime(_args?.ToArray() ?? []);
- break;
- case RenderingMode.DRM:
- builder.StartLinuxDrm(_args?.ToArray() ?? [], "/dev/dri/card1", 1.0);
- break;
- }
- }
-
- private static void SilenceConsole()
- {
- new Thread(() =>
- {
- Console.CursorVisible = false;
- while (true)
- Console.ReadKey(true);
- })
- { IsBackground = true }.Start();
- }
-
- private static IHost BuildHostApp()
- {
- var builder = Host.CreateApplicationBuilder();
-
- builder.Logging.ClearProviders();
- builder.Logging.AddConsole(options => options.FormatterName = nameof(ConsoleFormatter));
- builder.Logging.AddConsoleFormatter();
- builder.Logging.AddProvider(new FileLoggerProvider("full.log", true));
- builder.Logging.AddProvider(new FileLoggerProvider("last_run.log", false));
- builder.Services.AddSingleton();
-
- builder.Services.AddAmineContentCalibrationContext(builder.Configuration);
- builder.Services.AddAmineContentResultsContext(builder.Configuration);
-
- builder.Services.AddLightsService("Hardware:Lights");
- builder.Services.AddTemperatureHumidityService("Hardware:TemperatureHumidity");
- builder.Services.AddIlluminatorService("Hardware:Illuminator");
- builder.Services.AddCameraService("Hardware:Camera", true);
- builder.Services.AddComputeResourcesService();
- builder.Services.AddImageStorageService(new DirectoryInfo("images"));
-
- builder.Services.AddViewsAndModels();
-
- var host = builder.Build();
- host.Services.GetRequiredService();
-
- using (var scope = host.Services.CreateScope())
- {
- var context = scope.ServiceProvider.GetRequiredService();
- context.Database.Migrate();
- }
- using (var scope = host.Services.CreateScope())
- {
- var context = scope.ServiceProvider.GetRequiredService();
- context.Database.Migrate();
- }
-
- return host;
- }
-
- private static AppBuilder BuildAvaloniaApp()
- => AppBuilder.Configure()
- .UsePlatformDetect()
- .UseSkia()
- .LogToTrace()
- .With(new X11PlatformOptions
- {
- RenderingMode = [X11RenderingMode.Egl]
- })
- .With(new EglDisplayOptions
- {
- SupportsContextSharing = true
- });
-}
diff --git a/GSS2.Test/ViewModels/MainViewModel.cs b/GSS2.Test/ViewModels/MainViewModel.cs
deleted file mode 100644
index 96777f8..0000000
--- a/GSS2.Test/ViewModels/MainViewModel.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using CommunityToolkit.Mvvm.ComponentModel;
-using CommunityToolkit.Mvvm.Input;
-
-using GSS2.Core.Hardware;
-using GSS2.UI.Core.ViewModels;
-
-namespace GSS2.Test.ViewModels;
-
-public partial class MainViewModel : ViewModelBase
-{
- private readonly ILogger _logger;
- private readonly CameraService _cameraService;
- private readonly IlluminatorService _illuminatorService;
-
- [ObservableProperty] private CameraViewModel _cameraViewModel;
- [ObservableProperty] private ResourcesViewModel _resourcesViewModel;
- [ObservableProperty] private IlluminatorControllerViewModel _illuminatorControllerViewModel;
- [ObservableProperty] private OpenCvSharp.Mat? _image1;
- [ObservableProperty] private OpenCvSharp.Mat? _image2;
- [ObservableProperty] private OpenCvSharp.Mat? _image3;
- [ObservableProperty] private OpenCvSharp.Mat? _image4;
- [ObservableProperty] private IRelayCommand _buttonCaptureClick;
- [ObservableProperty] private IRelayCommand _buttonUpClick;
- [ObservableProperty] private IRelayCommand _buttonDownClick;
- [ObservableProperty] private int _currentIndex;
- [ObservableProperty] private bool _canScrollForward;
- [ObservableProperty] private bool _canScrollBackward;
-
- public MainViewModel(ILogger logger, CameraViewModel cameraViewModel, ResourcesViewModel resourcesViewModel, IlluminatorControllerViewModel illuminatorControllerViewModel, CameraService cameraService, IlluminatorService illuminatorService)
- {
- _logger = logger;
- _logger.LogInformation("Initialization");
-
- _cameraService = cameraService;
- _illuminatorService = illuminatorService;
- CameraViewModel = cameraViewModel;
- ResourcesViewModel = resourcesViewModel;
- IlluminatorControllerViewModel = illuminatorControllerViewModel;
- ButtonCaptureClick = new RelayCommand(() =>
- {
- Task.Run(async () =>
- {
- _illuminatorService.TurnOn();
- _illuminatorService.SetIntensity(1, 0, 0);
- await _cameraService.CaptureImage(CancellationToken.None, 3).ContinueWith(image => Image1 = image.Result);
- _illuminatorService.SetIntensity(0, 1, 1);
- await _cameraService.CaptureImage(CancellationToken.None, 3).ContinueWith(image => Image2 = image.Result);
- _illuminatorService.SetIntensity(0, 1, 0);
- await _cameraService.CaptureImage(CancellationToken.None, 3).ContinueWith(image => Image3 = image.Result);
- _illuminatorService.SetIntensity(0, 0, 1);
- await _cameraService.CaptureImage(CancellationToken.None, 3).ContinueWith(image => Image4 = image.Result);
- _illuminatorService.SetIntensity(0, 0, 0);
- _illuminatorService.TurnOff();
- });
- });
- ButtonUpClick = new RelayCommand(() => CurrentIndex--);
- ButtonDownClick = new RelayCommand(() => CurrentIndex++);
-
- _logger.LogInformation("Initialized");
- }
-}
\ No newline at end of file
diff --git a/GSS2.Test/Views/MainView.axaml b/GSS2.Test/Views/MainView.axaml
deleted file mode 100644
index 6dd5f93..0000000
--- a/GSS2.Test/Views/MainView.axaml
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/GSS2.Test/Views/MainView.axaml.cs b/GSS2.Test/Views/MainView.axaml.cs
deleted file mode 100644
index bd1c0e9..0000000
--- a/GSS2.Test/Views/MainView.axaml.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using Avalonia.Controls;
-
-namespace GSS2.Test.Views;
-
-public partial class MainView : UserControl
-{
- private readonly ILogger _logger;
-
- public MainView(ILogger logger)
- {
- _logger = logger;
- InitializeComponent();
- _logger.LogInformation("{} initialized", nameof(MainView));
- }
-}
\ No newline at end of file
diff --git a/GSS2.Test/app.manifest b/GSS2.Test/app.manifest
deleted file mode 100644
index eca2788..0000000
--- a/GSS2.Test/app.manifest
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/GSS2.Test/appsettings.json b/GSS2.Test/appsettings.json
deleted file mode 100644
index 5187e69..0000000
--- a/GSS2.Test/appsettings.json
+++ /dev/null
@@ -1,82 +0,0 @@
-{
- "Logging": {
- "LogLevel": {
- "Default": "Information",
- "Microsoft.Hosting.Lifetime": "Information",
- "Microsoft.EntityFrameworkCore.Migrations": "Warning",
- "Microsoft.EntityFrameworkCore.Database.Command": "Warning",
- "GSS2.Core.Hardware.LightsService": "Information",
- "GSS2.Core.Hardware.IlluminatorService": "Information",
- "GSS2.Core.Hardware.CameraService": "Information",
- "LibCamera": "Information",
- "LibCamera-Camera": "Information",
- "LibCamera-RPI": "Information",
- "LibCamera-DeviceEnumerator": "Information",
- "LibCamera-IPAProxy": "Information",
- "LibCamera-V4L2": "Information",
- "LibCamera-RPISTREAM": "Information",
- "LibCamera-WRAPPER": "Information",
- "Avalonia.*": "Warning"
- }
- },
- "ConnectionStrings": {
- "AmineContentCalibrationDatabasePath": "AmineContentCalibration.db",
- "AmineContentResultsDatabasePath": "AmineContentResults.db"
- },
- "Hardware": {
- "Illuminator": {
- "WhitePwmPin": 13,
- "Uv254PwmPin": 18,
- "Uv365PwmPin": 12,
- "WhiteRelayPin": 16,
- "Uv254RelayPin": 15,
- "Uv365RelayPin": 20,
- "FanPin": 21,
- "PwmFrequency": 200,
- "MaxWhitePwmDuty": 1.0,
- "MaxUv254PwmDuty": 1.0,
- "MaxUv365PwmDuty": 1.0
- },
- "Camera": {
- "CameraId": "/base/axi/pcie@1000120000/rp1/i2c@70000/imx477@1a",
- "ViewFinderFrameBufferCount": 5,
- "ViewFinderWidth": 4056,
- "ViewFinderHeight": 3040,
- "ViewFinderFps": 30,
- "ImageCaptureFrameBufferCount": 5,
- "ImageCaptureWidth": 4056,
- "ImageCaptureHeight": 3040,
- "CameraHardSettings": {
- "AeEnable": false,
- "ExposureValue": 8.0,
- "ExposureTime": 30000,
- "ExposureTimeMode": "ExposureTimeModeManual",
- "AnalogueGain": 23.0,
- "AnalogueGainMode": "AnalogueGainModeManual",
- "Brightness": 0.0,
- "Contrast": 1.0,
- "AwbEnable": false,
- "ColourGains": [
- 3.2,
- 1.0
- ],
- "HdrMode": "HdrModeOff",
- "NoiseReductionMode": "NoiseReductionModeOff",
- "StatsOutputEnable": true,
- "SyncMode": "SyncModeOff",
- "CnnEnableInputTensor": false
- },
- "DecodeGainR": 3.2,
- "DecodeGainG": 1.0,
- "DecodeGainB": 1.0,
- "DecodeBlackLevel": 4096
- },
- "TemperatureHumidity": {
- "Bus": 6,
- "Address": 69
- },
- "Lights": {
- "ServerAddress": "http://127.0.0.1:50051"
- }
- }
-}
\ No newline at end of file