using Azaion.Common.DTO; using Azaion.Common.DTO.Config; using Azaion.Common.Extensions; using Microsoft.Extensions.Options; namespace Azaion.Common.Services.Inference; public interface IInferenceService { Task RunInference(List mediaPaths, CameraConfig cameraConfig, CancellationToken ct = default); CancellationTokenSource InferenceCancelTokenSource { get; set; } CancellationTokenSource CheckAIAvailabilityTokenSource { get; set; } void StopInference(); } // SHOULD BE ONLY ONE INSTANCE OF InferenceService. Do not add ANY NotificationHandler to it! // _inferenceCancelTokenSource should be created only once. public class InferenceService : IInferenceService { private readonly IInferenceClient _client; private readonly IAzaionApi _azaionApi; private readonly IOptions _aiConfigOptions; public InferenceService(IInferenceClient client, IAzaionApi azaionApi, IOptions aiConfigOptions) { _client = client; _azaionApi = azaionApi; _aiConfigOptions = aiConfigOptions; _ = Task.Run(async () => await CheckAIAvailabilityStatus()); } public CancellationTokenSource InferenceCancelTokenSource { get; set; } = new(); public CancellationTokenSource CheckAIAvailabilityTokenSource { get; set; } = new(); private async Task CheckAIAvailabilityStatus() { CheckAIAvailabilityTokenSource = new CancellationTokenSource(); while (!CheckAIAvailabilityTokenSource.IsCancellationRequested) { _client.Send(RemoteCommand.Create(CommandType.AIAvailabilityCheck)); await Task.Delay(10000, CheckAIAvailabilityTokenSource.Token); } } public async Task RunInference(List mediaPaths, CameraConfig cameraConfig, CancellationToken ct = default) { InferenceCancelTokenSource = new CancellationTokenSource(); _client.Send(RemoteCommand.Create(CommandType.Login, _azaionApi.Credentials)); var aiConfig = _aiConfigOptions.Value; aiConfig.Paths = mediaPaths; aiConfig.Altitude = (double)cameraConfig.Altitude; aiConfig.CameraFocalLength = (double)cameraConfig.CameraFocalLength; aiConfig.CameraSensorWidth = (double)cameraConfig.CameraSensorWidth; _client.Send(RemoteCommand.Create(CommandType.Inference, aiConfig)); using var combinedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(ct, InferenceCancelTokenSource.Token); await combinedTokenSource.Token.AsTask(); } public void StopInference() => _client.Stop(); }