using Cysharp.Threading.Tasks; using System; using System.IO; using System.Threading; using UnityEngine; namespace Periscope { public static class PeriscopeManager { public static bool AutoRegime { get; private set; } public static PeriscopeConfig config; private static PeriscopeState state; private static CancellationTokenSource _gameCts; private static bool initialized = false; public static void Init(CancellationTokenSource gameCts) { _gameCts = gameCts; config = LoadConfigOrDefault(); initialized = true; StopAllForce(); } public static void UpManually() { if (!AutoRegime) Up(); } public static void DownManually() { if (!AutoRegime) Down(); } public static void StopManually() { if (!AutoRegime) Stop(); } private static void Stop() { if (CanExecute(requiredState: PeriscopeState.Stopped)) { var command = state switch { PeriscopeState.MovingDown => config.StopDownCommand, PeriscopeState.MovingUp => config.StopUpCommand, _ => string.Empty, }; if (string.IsNullOrEmpty(command)) StopAllForce(); ComPortController.Send(command); state = PeriscopeState.Stopped; } } public static void StopAllForce() { if (!initialized) return; ComPortController.Send(config.StopUpCommand); ComPortController.Send(config.StopDownCommand); state = PeriscopeState.Stopped; } private static void Up() { if (CanExecute(requiredState: PeriscopeState.MovingUp)) { ComPortController.Send(config.MoveUpCommand); state = PeriscopeState.MovingUp; } } private static void Down() { if (CanExecute(requiredState: PeriscopeState.MovingDown)) { ComPortController.Send(config.MoveDownCommand); state = PeriscopeState.MovingDown; } } private static bool CanExecute(PeriscopeState requiredState) => initialized && state != requiredState; public static void MoveUpToEnd() { if (AutoRegime) return; MoveWithTiming(config.MoveUpCommand, config.MoveUpToEndTimeMs, _gameCts.Token).Forget(); } public static void MoveCenter() { if (AutoRegime) return; MoveWithTiming(config.MoveDownCommand, config.MoveToCenterTimeMs, _gameCts.Token).Forget(); } private static async UniTask MoveWithTiming(string moveCommand, int timeMs, CancellationToken token) { if (!initialized) return; AutoRegime = true; StopAllForce(); await UniTask.Delay(20, cancellationToken: token); ComPortController.Send(moveCommand); await UniTask.Delay(timeMs, cancellationToken: token); StopAllForce(); AutoRegime = false; } private static PeriscopeConfig LoadConfigOrDefault() { string fp = Path.Combine("Configs", "Periscope.json"); PeriscopeConfig config; try { if (File.Exists(Path.Combine(Application.streamingAssetsPath, fp))) { config = FileUtil.LoadJson(fp, FileUtil.AppDirectory.Streaming).Data; if (config != null) return config; } config = new PeriscopeConfig(); FileUtil.SaveJson(fp, FileUtil.AppDirectory.Streaming, config); Debug.Log($"Создан новый Periscope с настройками по умолчанию и сохранен в {fp}"); } catch (Exception ex) { Debug.LogError($"Ошибка при загрузке или создании ControllerDevice: {ex.Message}"); config = new PeriscopeConfig(); } return config; } [Serializable] public class PeriscopeConfig { //Команды public string MoveUpCommand = "2101"; public string StopUpCommand = "2100"; public string MoveDownCommand = "2111"; public string StopDownCommand = "2110"; //Тайминги public int MoveUpToEndTimeMs = 10000; public int MoveToCenterTimeMs = 3000; } public enum PeriscopeState { Stopped, MovingUp, MovingDown } } }