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.Text;
using System.Runtime.InteropServices;
using Microsoft.Extensions.Logging;
using LibCameraSharp;
using GSS2.Core.Extentions;
using GSS2.Core.Abstractions;
using Stream = LibCameraSharp.Stream;
namespace GSS2.Core.Hardware;
@@ -26,31 +32,6 @@ public class CameraService : IDisposable
public ulong Length { 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]
private enum State
{
@@ -63,6 +44,30 @@ public class CameraService : IDisposable
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 readonly ILogger<CameraService> _logger;
private readonly CameraServiceConfiguration _configuration;
@@ -77,40 +82,41 @@ public class CameraService : IDisposable
private Stream? _viewFinderStream;
private Stream? _imageCaptureStream;
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();
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)
{
_logger = logger;
_logger.LogInformation("CameraService initialization");
_logger.LogInformation("Initialization");
try
{
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;
}
_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}
");
_logger.LogInformation("Using following configuration: \n{}", _configuration.ToString("\n", 4));
if (autoInitialize)
Initialize(CancellationToken.None);
}
catch (Exception e)
{
_logger.LogCritical(e, "An exception occurred while initialization");
throw;
}
_logger.LogInformation("Initialized");
}
public async Task InitializeAsync(CancellationToken cancellationToken)
{
@@ -664,11 +670,6 @@ public class CameraService : IDisposable
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()
{
if (_camera is null)
@@ -34,6 +34,8 @@ public class ComputeResourcesService
public ComputeResourcesService(ILogger<ComputeResourcesService> logger)
{
_logger = logger;
_logger.LogInformation("Initialization");
_logger.LogInformation("Initialized");
}
public ComputeResourcesSnapshot GetSnapshot()
+13 -24
View File
@@ -1,12 +1,15 @@
using System.Device.Gpio;
using System.Device.Pwm;
using Microsoft.Extensions.Logging;
using GSS2.Core.Abstractions;
namespace GSS2.Core.Hardware;
public class IlluminatorService : IDisposable
{
public class IlluminatorServiceConfiguration
public record IlluminatorServiceConfiguration : ServiceConfigurationBase
{
public static IlluminatorServiceConfiguration Default => new IlluminatorServiceConfiguration
{
@@ -76,38 +79,22 @@ public class IlluminatorService : IDisposable
{
_logger = logger;
_logger.LogInformation("Illuminator initialization");
_logger.LogInformation("Initialization");
try
{
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;
}
_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}
");
_logger.LogInformation("Using following configuration: \n{}", _configuration.ToString("\n", 4));
CheckPwmPin(_configuration.WhitePwmPin);
CheckPwmPin(_configuration.Uv254PwmPin);
CheckPwmPin(_configuration.Uv365PwmPin);
try
{
_gpio = new GpioController();
_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));
@@ -120,9 +107,11 @@ public class IlluminatorService : IDisposable
}
catch (Exception e)
{
_logger.LogCritical(e, "An exception occurred while illuminator initialization");
_logger.LogCritical(e, "An exception occurred while initialization");
throw;
}
_logger.LogInformation("Initialized");
}
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.Runtime.CompilerServices;
using Microsoft.Extensions.Logging;
using Grpc.Core;
using Grpc.Net.Client;
using GSS2.LightsControl.CSharpClient;
using GSS2.Core.Abstractions;
namespace GSS2.Core.Hardware;
public class LightsService
{
public class LightsServiceConfiguration()
public record LightsServiceConfiguration : ServiceConfigurationBase
{
public static LightsServiceConfiguration Default => new LightsServiceConfiguration
{
@@ -27,24 +31,28 @@ public class LightsService
{
_logger = logger;
_logger.LogInformation("Lights initialization");
_logger.LogInformation("Initialization");
try
{
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;
}
_logger.LogDebug(@$"Lights use following configuration:
ServerAddress: {_configuration.ServerAddress}
");
_logger.LogInformation("Using following configuration: \n{}", _configuration.ToString("\n", 4));
_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)
{
@@ -1,11 +1,14 @@
using System.Device.I2c;
using Microsoft.Extensions.Logging;
using GSS2.Core.Abstractions;
namespace GSS2.Core.Hardware;
public class TemperatureHumidityService : IDisposable
{
public class TemperatureHumidityServiceConfiguration
public record TemperatureHumidityServiceConfiguration : ServiceConfigurationBase
{
public static TemperatureHumidityServiceConfiguration Default => new TemperatureHumidityServiceConfiguration
{
@@ -26,32 +29,27 @@ public class TemperatureHumidityService : IDisposable
{
_logger = logger;
_logger.LogInformation("Temperature and humidity sensor 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}
");
_logger.LogInformation("Initialization");
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));
}
catch (Exception e)
{
_logger.LogCritical(e, "An exception occurred while temperature and humidity sensor initialization");
_logger.LogCritical(e, "An exception occurred while initialization");
throw;
}
_logger.LogInformation("Initialized");
}
public (double temperature, double relativeHumidity) Measure(int measurementsCount = 1, bool checkCrc = true, CancellationToken cancellationToken = default)