Files
XRLib/Assets/Scripts/UVC/Factory/Playback/PlaybackService.cs
2025-07-28 19:59:35 +09:00

249 lines
12 KiB
C#

#nullable enable
using Best.HTTP;
using Cysharp.Threading.Tasks;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using UnityEngine;
using UVC.Data.Core;
using UVC.Data.Http;
using UVC.Factory.Playback.UI;
using UVC.Util;
namespace UVC.Factory.Playback
{
public class PlaybackService
{
#region Singleton
private static readonly PlaybackService instance = new PlaybackService(new PlaybackRepository());
public static PlaybackService Instance => instance;
static PlaybackService() { }
#endregion
public static readonly string PlaybackFolderPath = Path.Combine(Application.persistentDataPath, "playback");//streamingAssetsPath, "playback"); appData 폴더로 변경
private readonly PlaybackRepository repository;
private string date;
private string time;
private string fileName;
public Action OnExitPlayback;
private float timeScale = 1.0f;
public float TimeScale
{
get => timeScale;
internal set
{
if (value < 1f) value = 1f;
if (timeScale != value)
{
timeScale = value;
//Time.timeScale = timeScale;
OnChangeTimeScale?.Invoke(timeScale);
}
}
}
public Action<float> OnChangeTimeScale;
public PlaybackService(PlaybackRepository repository)
{
this.repository = repository;
}
public async UniTask<Dictionary<string, Dictionary<string, string>>?> RequestDataAsync()
{
Dictionary<string, Dictionary<string, string>>? data = await repository.RequestPlaybackDateList();
return data;
}
public async UniTask DispatchBaseInfoData(string date, string time, string fileName, string minute = "00", string second = "00")
{
await UniTask.RunOnThreadPool(async () =>
{
//헝가리 시간임
this.date = date;
this.time = time;
this.fileName = fileName;
DateTime dateTime = DateTimeUtil.UtcParse($"{date}T{int.Parse(time).ToString("00")}:{minute}:{second}.000Z");
string formatTime = DateTimeUtil.FormatTime(dateTime);
//baseInfo 가져오기
List <PlaybackSQLiteDataEntity> list = await repository.SelectBySecondBaseInfo(date, fileName, formatTime);
if (list.Count > 0)
{
HttpRequestConfig httpRequestConfig = new HttpRequestConfig("");
httpRequestConfig.SetUpdatedDataOnly(true);
httpRequestConfig.SetSplitResponseByKey(true);
httpRequestConfig.AddSplitConfig("AGV", DataMapperValidator.Get("AGV"));
httpRequestConfig.AddSplitConfig("ALARM", DataMapperValidator.Get("ALARM"));
foreach (var item in list)
{
HttpDataProcessor.ProcessSplitResponse(httpRequestConfig, item.data);
}
}
});
}
/// <summary>
///
/// </summary>
/// <param name="second">0 ~ 3600</param>
public async UniTask DispatchRealTimeData(int second, int speed)
{
await UniTask.RunOnThreadPool(async () =>
{
int newSecond = second;
if (newSecond > 36000) newSecond = 36000;
//utc 시간으로 변환
DateTime dateTime = DateTimeUtil.UtcParse($"{date}T{int.Parse(time).ToString("00")}:00:00.000Z").AddSeconds(newSecond);//.Add(-DateTimeUtil.UtcKoreaGap);
string formatTime = DateTimeUtil.FormatTime(dateTime);
List<PlaybackSQLiteDataEntity> list = await repository.SelectBySecondAsync(date, fileName, formatTime, 1);
//Debug.Log($"DispatchRealTimeData {date} {time} {formatTime} {newSecond} {list.Count}");
if (list.Count > 0)
{
HttpRequestConfig httpRequestConfig = new HttpRequestConfig("");
httpRequestConfig.SetUpdatedDataOnly(true);
httpRequestConfig.SetSplitResponseByKey(true);
httpRequestConfig.AddSplitConfig("AGV", DataMapperValidator.Get("AGV"));
httpRequestConfig.AddSplitConfig("ALARM", DataMapperValidator.Get("ALARM"));
foreach (var item in list)
{
HttpDataProcessor.ProcessSplitResponse(httpRequestConfig, item.data);
}
}
});
}
public async Task StartAsync(UIPlaybackListItemData data)
{
timeScale = 1.0f; //기본 시간 스케일 설정
UIPlayback.Instance.Show();
await UIPlayback.Instance.SetData(data.date, data.time, data.sqlFileName);
}
public void Exit()
{
OnExitPlayback?.Invoke();
}
public HTTPRequest? ReadyData(string date, string time, string fileName, Action<long, long, float> OnProgress, Action<string> OnComplete)
{
//date : "2024-12-05"
//fileName : "2024-12-05_0.sqlite.7z"
string playbackPath = PlaybackService.PlaybackFolderPath;
string tempPath = Path.Combine(playbackPath, "temp");//한국 시간으로 변경하기 때문에 임시 폴더 만들어서 압축 해제 후 이동
string datePath = Path.Combine(playbackPath, date);
var fileNameArr = fileName.Split(".");
string zipFilePath = Path.Combine(datePath, fileName);
string sqlFilePath = Path.Combine(datePath, fileNameArr[0] + ".sqlite");
DateTime utcDateTime = DateTimeUtil.Parse(fileNameArr[0], "yyyy-MM-dd_H");//.Add(-DateTimeUtil.UtcKoreaGap);
string utcDatePath = Path.Combine(playbackPath, utcDateTime.ToString("yyyy-MM-dd"));
string utcFileName = utcDateTime.ToString("yyyy-MM-dd_H") + "." + fileNameArr[1] + "." + fileNameArr[2];
var utcFileNameArr = utcFileName.Split(".");
string utcZipFilePath = Path.Combine(tempPath, utcFileName);
string utcSqlFilePath = Path.Combine(tempPath, utcFileNameArr[0] + ".sqlite");
if (!Directory.Exists(playbackPath)) Directory.CreateDirectory(playbackPath);
if (!Directory.Exists(datePath)) Directory.CreateDirectory(datePath);
if (!Directory.Exists(utcDatePath)) Directory.CreateDirectory(utcDatePath);
if (!Directory.Exists(tempPath)) Directory.CreateDirectory(tempPath);
if (File.Exists(sqlFilePath))
{
Debug.Log($"ONREADY SQP FILE");
if (OnProgress != null) OnProgress.Invoke(100, 100, 1.0f);
if (OnComplete != null) OnComplete.Invoke(null);
return null;
}
else
{
long downloadTotal = 0;
return repository.DownloadPlaybackData(utcFileName, utcZipFilePath,
(long progress, long length) =>
{
float percent = (float)progress / (float)length;
Debug.Log($"DownloadPlaybackData OnProgress:{percent}");
if (OnProgress != null) OnProgress.Invoke(progress, length, percent / 2);
downloadTotal = length;
}, async () =>
{
await UniTask.Delay(500);
Debug.Log($"DownloadPlaybackData OnComplete");
if (File.Exists(utcZipFilePath))
{
if (OnProgress != null) OnProgress.Invoke(50, 100, 0.5f);
//압축해제 후
var zipper = new Zipper();
string errorMessage = await zipper.Decompress(utcZipFilePath, tempPath, (long read, long total, float percent) =>
{
if (OnProgress != null)
{
bool isComplte = false;
float percentRate = 0.5f + percent / 2;
if (percentRate > 0.99)
{
percentRate = 0.99f;
isComplte = true;
}
OnProgress.Invoke(downloadTotal + read, downloadTotal + total, 0.5f + percent / 2);
if (isComplte)
{
Debug.Log($" DownloadReadData :{downloadTotal + read} , DownloadTotalData :{downloadTotal + total} ,DownloadPlaybackData OnProgress:{percent}");
}
}
});
Debug.Log($"zipper1 errorMessage:{errorMessage} utcSqlFilePath:{utcSqlFilePath} sqlFilePath:{sqlFilePath} utcZipFilePath:{utcZipFilePath}");
////파일 접근 문제면 2회 0.5초 후에 다시 실행.
//if (errorMessage == "Could not open input(7z) file")
//{
// await UniTask.Delay(500);
// errorMessage = await zipper.Decompress(utcZipFilePath, tempPath, (long read, long total, float percent) =>
// {
// if (OnProgress != null) OnProgress.Invoke(downloadTotal + read, downloadTotal + total, 0.5f + percent / 2);
// });
// Debug.Log($"zipper2 errorMessage:{errorMessage} utcSqlFilePath:{utcSqlFilePath} sqlFilePath:{sqlFilePath} utcZipFilePath:{utcZipFilePath}");
//}
//if (errorMessage == "Could not open input(7z) file")
//{
// await UniTask.Delay(500);
// errorMessage = await zipper.Decompress(utcZipFilePath, tempPath, (long read, long total, float percent) =>
// {
// if (OnProgress != null) OnProgress.Invoke(downloadTotal + read, downloadTotal + total, 0.5f + percent / 2);
// });
// Debug.Log($"zipper3 errorMessage:{errorMessage} utcSqlFilePath:{utcSqlFilePath} sqlFilePath:{sqlFilePath} utcZipFilePath:{utcZipFilePath}");
//}
await UniTask.RunOnThreadPool(() =>
{
//압축해제 한 파일 이동
if (File.Exists(utcSqlFilePath))
{
//동일한 파일명이 있을경우 제거후 다시
File.Copy(utcSqlFilePath, sqlFilePath);
File.Delete(utcSqlFilePath);
}
//zip 파일 삭제
File.Delete(utcZipFilePath);
});
if (OnComplete != null) OnComplete.Invoke(errorMessage);
}
},
(string? error) =>
{
Debug.Log($"DownloadPlaybackData OnError:{error}");
if (OnComplete != null) OnComplete.Invoke(error);
});
}
}
}
}