using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEngine.Events;
namespace DanroJump.Hardware.Com
{
///
/// Единая процедура выдачи капсулы через хоппер: запуск мотора, ожидание датчика и остановка.
///
public static class ComHopperDispenser
{
public const string StartMotorCommand = "301";
public const string StopMotorCommand = "300";
public const int DefaultTimeoutSeconds = 10;
public static UniTask DispenseAsync(
IComSystem com,
CancellationToken cancellationToken = default)
{
return DispenseAsync(com, TimeSpan.FromSeconds(DefaultTimeoutSeconds), cancellationToken);
}
public static async UniTask DispenseAsync(
IComSystem com,
TimeSpan timeout,
CancellationToken cancellationToken = default)
{
if (com == null)
{
return ComHopperDispenseResult.Failure("COM-система недоступна.");
}
if (!com.IsRunning)
{
return ComHopperDispenseResult.Failure("COM-система не запущена.");
}
if (!com.SendToMain(StartMotorCommand))
{
return ComHopperDispenseResult.Failure("Не удалось отправить команду запуска хоппера.");
}
var sensorTriggered = new UniTaskCompletionSource();
UnityAction onTriggered = () => sensorTriggered.TrySetResult();
com.HopperSensorTriggered.AddListener(onTriggered);
try
{
var winner = await UniTask.WhenAny(
sensorTriggered.Task,
UniTask.Delay(timeout, DelayType.Realtime, PlayerLoopTiming.Update, cancellationToken));
return winner == 0
? ComHopperDispenseResult.Success("Капсула выдана успешно.")
: ComHopperDispenseResult.Failure($"Датчик хоппера не сработал за {timeout.TotalSeconds:0.#} сек.");
}
finally
{
com.HopperSensorTriggered.RemoveListener(onTriggered);
com.SendToMain(StopMotorCommand);
}
}
}
public readonly struct ComHopperDispenseResult
{
private ComHopperDispenseResult(bool isSuccess, string message)
{
IsSuccess = isSuccess;
Message = message ?? string.Empty;
}
public bool IsSuccess { get; }
public string Message { get; }
public static ComHopperDispenseResult Success(string message)
{
return new ComHopperDispenseResult(true, message);
}
public static ComHopperDispenseResult Failure(string message)
{
return new ComHopperDispenseResult(false, message);
}
}
}