refactor: hardware services

This commit is contained in:
2026-02-12 08:34:19 +03:00
parent eaa20dbe75
commit 691129eff4
6 changed files with 126 additions and 116 deletions
@@ -0,0 +1,12 @@
namespace GSS2.Core.Abstractions;
public abstract record ServiceConfigurationBase
{
public virtual string ToString(string separator, int indent)
{
List<string?> strs = new List<string?>();
foreach (var prop in GetType().GetProperties())
strs.Add($"{prop.Name}: {prop.GetValue(this)}");
return string.Join(separator, strs.Select(s => $"{new string(' ', indent)}{s}"));
}
}
+52 -51
View File
@@ -1,9 +1,15 @@
using System.Runtime.InteropServices;
using Microsoft.Extensions.Logging;
using LibCameraSharp;
using Stream = LibCameraSharp.Stream;
using System.Buffers; using System.Buffers;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Extensions.Logging;
using LibCameraSharp;
using GSS2.Core.Extentions; using GSS2.Core.Extentions;
using GSS2.Core.Abstractions;
using Stream = LibCameraSharp.Stream;
namespace GSS2.Core.Hardware; namespace GSS2.Core.Hardware;
@@ -26,31 +32,6 @@ public class CameraService : IDisposable
public ulong Length { get; init; } public ulong Length { get; init; }
public ulong AlignedOffset { get; init; } public ulong AlignedOffset { get; init; }
} }
public class CameraServiceConfiguration
{
public static CameraServiceConfiguration Default => new CameraServiceConfiguration
{
CameraId = "",
ViewFinderFrameBufferCount = 5,
ViewFinderWidth = 1920,
ViewFinderHeight = 1080,
ViewFinderFps = 30,
ImageCaptureFrameBufferCount = 2,
ImageCaptureWidth = 4056,
ImageCaptureHeight = 3080,
};
public string CameraId { get; set; } = "";
public int ViewFinderFrameBufferCount { get; set; }
public int ViewFinderWidth { get; set; }
public int ViewFinderHeight { get; set; }
public int ViewFinderFps { get; set; }
public int ImageCaptureFrameBufferCount { get; set; }
public int ImageCaptureWidth { get; set; }
public int ImageCaptureHeight { get; set; }
}
[Flags] [Flags]
private enum State private enum State
{ {
@@ -63,6 +44,30 @@ public class CameraService : IDisposable
ImageCaptureFrameBuffersMapped = 1 << 6 ImageCaptureFrameBuffersMapped = 1 << 6
} }
public record CameraServiceConfiguration : ServiceConfigurationBase
{
public static CameraServiceConfiguration Default => new CameraServiceConfiguration
{
CameraId = "",
ViewFinderFrameBufferCount = 5,
ViewFinderWidth = 4056,
ViewFinderHeight = 3080,
ViewFinderFps = 30,
ImageCaptureFrameBufferCount = 2,
ImageCaptureWidth = 4056,
ImageCaptureHeight = 3080
};
public string CameraId { get; set; } = "";
public int ViewFinderFrameBufferCount { get; set; }
public int ViewFinderWidth { get; set; }
public int ViewFinderHeight { get; set; }
public int ViewFinderFps { get; set; }
public int ImageCaptureFrameBufferCount { get; set; }
public int ImageCaptureWidth { get; set; }
public int ImageCaptureHeight { get; set; }
}
private bool _disposedValue; private bool _disposedValue;
private readonly ILogger<CameraService> _logger; private readonly ILogger<CameraService> _logger;
private readonly CameraServiceConfiguration _configuration; private readonly CameraServiceConfiguration _configuration;
@@ -77,40 +82,41 @@ public class CameraService : IDisposable
private Stream? _viewFinderStream; private Stream? _viewFinderStream;
private Stream? _imageCaptureStream; private Stream? _imageCaptureStream;
private List<MappedBuffer>? _imageCaptureMappedBuffers; private List<MappedBuffer>? _imageCaptureMappedBuffers;
private System.Timers.Timer? _viewFinderTimer = null;
private System.Timers.ElapsedEventHandler? _viewFinderTimerElapsed = null;
private EventHandler<Camera.RequestCompletedEventArgs>? _viewFinderRequestComplitedHandler = null;
private readonly CancellationTokenSource _disposeCts = new CancellationTokenSource(); private readonly CancellationTokenSource _disposeCts = new CancellationTokenSource();
public bool IsImageCapturing { get; private set; } = false; public bool IsImageCapturing { get; private set; } = false;
public List<FrameBuffer> ViewFinderBufferQueue { get; private set; } = new List<FrameBuffer>();
public CameraService(ILogger<CameraService> logger, CameraServiceConfiguration? configuration = null, bool autoInitialize = false) public CameraService(ILogger<CameraService> logger, CameraServiceConfiguration? configuration = null, bool autoInitialize = false)
{ {
_logger = logger; _logger = logger;
_logger.LogInformation("CameraService initialization"); _logger.LogInformation("Initialization");
try
{
if (configuration is null) if (configuration is null)
{ {
_logger.LogWarning("CameraService configuration not set. Using default configuration."); configuration = CameraServiceConfiguration.Default;
_configuration = CameraServiceConfiguration.Default; _logger.LogWarning("Configuration not set. Using default configuration.");
} }
else
{
_configuration = configuration; _configuration = configuration;
} _logger.LogInformation("Using following configuration: \n{}", _configuration.ToString("\n", 4));
_logger.LogDebug(@$"CameraService use following configuration:
CameraId: {_configuration.CameraId}
ViewFinderFrameBufferCount: {_configuration.ViewFinderFrameBufferCount}
ViewFinderWidth: {_configuration.ViewFinderWidth}
ViewFinderHeight: {_configuration.ViewFinderHeight}
ViewFinderFps: {_configuration.ViewFinderFps}
ImageCaptureFrameBufferCount: {_configuration.ImageCaptureFrameBufferCount}
ImageCaptureWidth: {_configuration.ImageCaptureWidth}
ImageCaptureHeight: {_configuration.ImageCaptureHeight}
");
if (autoInitialize) if (autoInitialize)
Initialize(CancellationToken.None); Initialize(CancellationToken.None);
} }
catch (Exception e)
{
_logger.LogCritical(e, "An exception occurred while initialization");
throw;
}
_logger.LogInformation("Initialized");
}
public async Task InitializeAsync(CancellationToken cancellationToken) public async Task InitializeAsync(CancellationToken cancellationToken)
{ {
@@ -664,11 +670,6 @@ public class CameraService : IDisposable
return image; return image;
} }
public List<FrameBuffer> ViewFinderBufferQueue { get; private set; } = new List<FrameBuffer>();
private System.Timers.Timer? _viewFinderTimer = null;
private System.Timers.ElapsedEventHandler? _viewFinderTimerElapsed = null;
private EventHandler<Camera.RequestCompletedEventArgs>? _viewFinderRequestComplitedHandler = null;
public void StartViewFinder() public void StartViewFinder()
{ {
if (_camera is null) if (_camera is null)
@@ -34,6 +34,8 @@ public class ComputeResourcesService
public ComputeResourcesService(ILogger<ComputeResourcesService> logger) public ComputeResourcesService(ILogger<ComputeResourcesService> logger)
{ {
_logger = logger; _logger = logger;
_logger.LogInformation("Initialization");
_logger.LogInformation("Initialized");
} }
public ComputeResourcesSnapshot GetSnapshot() public ComputeResourcesSnapshot GetSnapshot()
+13 -24
View File
@@ -1,12 +1,15 @@
using System.Device.Gpio; using System.Device.Gpio;
using System.Device.Pwm; using System.Device.Pwm;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using GSS2.Core.Abstractions;
namespace GSS2.Core.Hardware; namespace GSS2.Core.Hardware;
public class IlluminatorService : IDisposable public class IlluminatorService : IDisposable
{ {
public class IlluminatorServiceConfiguration public record IlluminatorServiceConfiguration : ServiceConfigurationBase
{ {
public static IlluminatorServiceConfiguration Default => new IlluminatorServiceConfiguration public static IlluminatorServiceConfiguration Default => new IlluminatorServiceConfiguration
{ {
@@ -76,38 +79,22 @@ public class IlluminatorService : IDisposable
{ {
_logger = logger; _logger = logger;
_logger.LogInformation("Illuminator initialization"); _logger.LogInformation("Initialization");
try
{
if (configuration is null) if (configuration is null)
{ {
_logger.LogWarning("Illuminator configuration not set. Using default configuration."); configuration = IlluminatorServiceConfiguration.Default;
_configuration = IlluminatorServiceConfiguration.Default; _logger.LogWarning("Configuration not set. Using default configuration.");
} }
else
{
_configuration = configuration; _configuration = configuration;
} _logger.LogInformation("Using following configuration: \n{}", _configuration.ToString("\n", 4));
_logger.LogDebug(@$"Illuminator use following configuration:
WhitePwmPin: {_configuration.WhitePwmPin}
Uv254PwmPin: {_configuration.Uv254PwmPin}
Uv365PwmPin: {_configuration.Uv365PwmPin}
WhiteRelayPin: {_configuration.WhiteRelayPin}
Uv254RelayPin: {_configuration.Uv254RelayPin}
Uv365RelayPin: {_configuration.Uv365RelayPin}
FanPin: {_configuration.FanPin}
PwmFrequency: {_configuration.PwmFrequency}
MaxWhitePwmDuty: {_configuration.MaxWhitePwmDuty}
MaxUv254PwmDuty: {_configuration.MaxUv254PwmDuty}
MaxUv365PwmDuty: {_configuration.MaxUv365PwmDuty}
");
CheckPwmPin(_configuration.WhitePwmPin); CheckPwmPin(_configuration.WhitePwmPin);
CheckPwmPin(_configuration.Uv254PwmPin); CheckPwmPin(_configuration.Uv254PwmPin);
CheckPwmPin(_configuration.Uv365PwmPin); CheckPwmPin(_configuration.Uv365PwmPin);
try
{
_gpio = new GpioController(); _gpio = new GpioController();
_whitePwm = PwmChannel.Create(PinPwmChips[_configuration.WhitePwmPin], PinPwmChannels[_configuration.WhitePwmPin], _configuration.PwmFrequency, CalculateDuty(0, _configuration.MaxWhitePwmDuty)); _whitePwm = PwmChannel.Create(PinPwmChips[_configuration.WhitePwmPin], PinPwmChannels[_configuration.WhitePwmPin], _configuration.PwmFrequency, CalculateDuty(0, _configuration.MaxWhitePwmDuty));
_uv254Pwm = PwmChannel.Create(PinPwmChips[_configuration.Uv254PwmPin], PinPwmChannels[_configuration.Uv254PwmPin], _configuration.PwmFrequency, CalculateDuty(0, _configuration.MaxUv254PwmDuty)); _uv254Pwm = PwmChannel.Create(PinPwmChips[_configuration.Uv254PwmPin], PinPwmChannels[_configuration.Uv254PwmPin], _configuration.PwmFrequency, CalculateDuty(0, _configuration.MaxUv254PwmDuty));
@@ -120,9 +107,11 @@ public class IlluminatorService : IDisposable
} }
catch (Exception e) catch (Exception e)
{ {
_logger.LogCritical(e, "An exception occurred while illuminator initialization"); _logger.LogCritical(e, "An exception occurred while initialization");
throw; throw;
} }
_logger.LogInformation("Initialized");
} }
public void SetIntensity(double? white = null, double? uv365 = null, double? uv254 = null) public void SetIntensity(double? white = null, double? uv365 = null, double? uv254 = null)
+19 -11
View File
@@ -1,15 +1,19 @@
using System.Drawing; using System.Drawing;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Grpc.Core; using Grpc.Core;
using Grpc.Net.Client; using Grpc.Net.Client;
using GSS2.LightsControl.CSharpClient; using GSS2.LightsControl.CSharpClient;
using GSS2.Core.Abstractions;
namespace GSS2.Core.Hardware; namespace GSS2.Core.Hardware;
public class LightsService public class LightsService
{ {
public class LightsServiceConfiguration() public record LightsServiceConfiguration : ServiceConfigurationBase
{ {
public static LightsServiceConfiguration Default => new LightsServiceConfiguration public static LightsServiceConfiguration Default => new LightsServiceConfiguration
{ {
@@ -27,24 +31,28 @@ public class LightsService
{ {
_logger = logger; _logger = logger;
_logger.LogInformation("Lights initialization"); _logger.LogInformation("Initialization");
try
{
if (configuration is null) if (configuration is null)
{ {
_logger.LogWarning("Lights configuration not set. Using default configuration."); configuration = LightsServiceConfiguration.Default;
_configuration = LightsServiceConfiguration.Default; _logger.LogWarning("Configuration not set. Using default configuration.");
} }
else
{
_configuration = configuration; _configuration = configuration;
} _logger.LogInformation("Using following configuration: \n{}", _configuration.ToString("\n", 4));
_logger.LogDebug(@$"Lights use following configuration:
ServerAddress: {_configuration.ServerAddress}
");
_client = new Lights.LightsClient(GrpcChannel.ForAddress(_configuration.ServerAddress)); _client = new Lights.LightsClient(GrpcChannel.ForAddress(_configuration.ServerAddress));
} }
catch (Exception e)
{
_logger.LogCritical(e, "An exception occurred while initialization");
throw;
}
_logger.LogInformation("Initialized");
}
public async Task Run(CancellationToken cancellationToken) public async Task Run(CancellationToken cancellationToken)
{ {
@@ -1,11 +1,14 @@
using System.Device.I2c; using System.Device.I2c;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using GSS2.Core.Abstractions;
namespace GSS2.Core.Hardware; namespace GSS2.Core.Hardware;
public class TemperatureHumidityService : IDisposable public class TemperatureHumidityService : IDisposable
{ {
public class TemperatureHumidityServiceConfiguration public record TemperatureHumidityServiceConfiguration : ServiceConfigurationBase
{ {
public static TemperatureHumidityServiceConfiguration Default => new TemperatureHumidityServiceConfiguration public static TemperatureHumidityServiceConfiguration Default => new TemperatureHumidityServiceConfiguration
{ {
@@ -26,32 +29,27 @@ public class TemperatureHumidityService : IDisposable
{ {
_logger = logger; _logger = logger;
_logger.LogInformation("Temperature and humidity sensor initialization"); _logger.LogInformation("Initialization");
if (configuration is null)
{
_logger.LogWarning("Temperature and humidity sensor configuration not set. Using default configuration.");
_configuration = TemperatureHumidityServiceConfiguration.Default;
}
else
{
_configuration = configuration;
}
_logger.LogDebug(@$"Temperature and humidity sensor use following configuration:
Bus: {_configuration.Bus}
Address: {_configuration.Address}
");
try try
{ {
if (configuration is null)
{
configuration = TemperatureHumidityServiceConfiguration.Default;
_logger.LogWarning("Configuration not set. Using default configuration.");
}
_configuration = configuration;
_logger.LogInformation("Using following configuration: \n{}", _configuration.ToString("\n", 4));
_sensor = I2cDevice.Create(new I2cConnectionSettings(_configuration.Bus, _configuration.Address)); _sensor = I2cDevice.Create(new I2cConnectionSettings(_configuration.Bus, _configuration.Address));
} }
catch (Exception e) catch (Exception e)
{ {
_logger.LogCritical(e, "An exception occurred while temperature and humidity sensor initialization"); _logger.LogCritical(e, "An exception occurred while initialization");
throw; throw;
} }
_logger.LogInformation("Initialized");
} }
public (double temperature, double relativeHumidity) Measure(int measurementsCount = 1, bool checkCrc = true, CancellationToken cancellationToken = default) public (double temperature, double relativeHumidity) Measure(int measurementsCount = 1, bool checkCrc = true, CancellationToken cancellationToken = default)