Files
Studio/Assets/Scripts/Studio/Connect/StudioService.cs
jmaniuvc b5bcfb4ca9 저장
2025-05-23 20:36:02 +09:00

295 lines
9.9 KiB
C#

using Newtonsoft.Json.Linq;
using Studio.Setting.Connect;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using Studio;
using Studio.Core;
namespace Studio
{
public class StudioServiceTypeEventArgs : EventArgs
{
public readonly string Type;
Dictionary<string, string> Entitis;
public StudioServiceTypeEventArgs(string type, Dictionary<string, string> entity)
{
Type = type;
Entitis = entity;
}
}
public class StudioService : UnitySingleton<StudioService>
{
#region Singleton
#endregion
private Dictionary<string, Dictionary<string, EventHandler<StudioServiceTypeEventArgs>>> listenerIdMap;
private StudioRepoistory repository;
public bool isConnected
{
get
{
return repository.isConnected;
}
}
private Dictionary<string, float> updateTime = new();
private int totalRequestPacket;
private int totalResponsePacket;
private long maxElapsedTime;
private long totalElapsedTime;
private int maxReponesSize;
private int maxReuqestSize;
private string maxReuqestApi;
private string maxResponseApi;
private string maxResponseTimeApi;
public Dictionary<string, StudioEntityWithState<object>> apiData = new();
public Dictionary<string, (Dictionary<string, Dictionary<string, string>>, TimeSpan)> mqttData = new();
private Dictionary<string, DateTime> lastUpdateTime = new();
public event Action<string, StudioEntityWithState<object>> onAPIDataLoaded;
public event Action<string, Dictionary<string, Dictionary<string, string>>, TimeSpan> onMQTTDataLoaded;
bool isMQTTConnected;
//private string
private StudioService(StudioRepoistory repository)
{
this.repository = repository;
listenerIdMap = new Dictionary<string, Dictionary<string, EventHandler<StudioServiceTypeEventArgs>>>();
repository.OnTopicList += OnTopicList;
// repository.OnDetectedError += OnDetectedError;
}
public void ConnectMQTT()
{
if (isMQTTConnected)
return;
this.repository = new StudioRepoistory();
listenerIdMap = new Dictionary<string, Dictionary<string, EventHandler<StudioServiceTypeEventArgs>>>();
repository.OnTopicList += OnTopicList;
repository.MQTTConnect();
isMQTTConnected = true;
}
public void SubscribeMQTT(string topic)
{
repository.Subscribe(topic);
}
//Que에 담아둔다?
private void OnTopicList(string type, Dictionary<string, Dictionary<string, string>> entities)
{
DateTime now = DateTime.Now;
TimeSpan elapsedTime;
// elapsed 계산
if (lastUpdateTime.ContainsKey(type))
{
DateTime last = lastUpdateTime[type];
elapsedTime = now - last;
}
else
{
elapsedTime = TimeSpan.Zero;
}
lastUpdateTime[type] = now;
foreach (var idKey in entities)
{
UpdateTopicData(type, idKey.Key, idKey.Value);
}
if (!mqttData.ContainsKey(type))
{
mqttData.Add(type, (entities, elapsedTime));
}
else
{
mqttData[type] = (entities, elapsedTime);
}
onMQTTDataLoaded?.Invoke(type, entities, elapsedTime); // 나중에 클래스 밖으로 이동 필요
}
private async Task UpdateTopicData(string type, string id, Dictionary<string, string> entity)
{
if (!updateTime.ContainsKey(type))
updateTime.Add(type, 0.5f);
var time = updateTime[type];
var task = Task.Run(async () =>
{
var st = string.Empty;
st = $"{type}:";
int delayTime = (int)(time * 1000);
await Task.Delay(delayTime);
DispatchMachineEvent(type, id, entity);
});
}
private Dictionary<string, Dictionary<string, Dictionary<string, string>>> timelineEntity = new();
public bool TryGetRecentTimelineEntity(string type, string id, out Dictionary<string, string> result)
{
result = null;
if (!timelineEntity.ContainsKey(type))
{
timelineEntity[type] = new Dictionary<string, Dictionary<string, string>>();
return false;
}
if (!timelineEntity[type].ContainsKey(id))
{
timelineEntity[type][id] = new();
return false;
}
result = timelineEntity[type][id];
return result != null;
}
public void AddTypeListener(string type, string id, EventHandler<StudioServiceTypeEventArgs> listener)
{
if (!listenerIdMap.ContainsKey(type))
{
listenerIdMap.Add(type, new());
//Debug.LogError($"Key Value is missing!!!! -Key:{type}-");
}
if (!listenerIdMap[type].ContainsKey(id))
{
listenerIdMap[type][id] = listener;
}
else
{
listenerIdMap[type][id] += listener;
}
}
public async Task LoadBaseData(string url)
{
DateTime startTime = DateTime.Now;
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
StudioEntityWithState<object> data = await repository.BaseInfo(url);
sw.Stop();
DateTime endTime = DateTime.Now;
var t = sw.ElapsedMilliseconds;
if (data.State.Equals(APIState.Loaded))
{
if (!apiData.ContainsKey(url))
apiData.Add(url, new());
data.lastRequestTime = startTime;
data.lastResponseTime = endTime;
data.elapsedTime = sw.Elapsed;
apiData[url] = data;
CheckAPIBoarder(data.Entity.ToString(), data.ReqSize, url, t);
UpdateEntity(url, data.Entity.ToString());
}
else if (data.State == APIState.Error)
{
//TODO 에러메세지
Debug.Log($"APIState : Error , Message :{data.Message}");
}
onAPIDataLoaded?.Invoke(url, data); // 나중에 클래스 밖으로 이동 필요
}
private void CheckAPIBoarder(string data, int reqSize, string url, long time)
{
var byteSize = System.Text.Encoding.Default.GetBytes(data).Length;
if (maxElapsedTime < time)
{
maxElapsedTime = time;
maxResponseTimeApi = url;
}
if (maxReponesSize < byteSize)
{
maxReponesSize = byteSize;
maxResponseApi = url;
}
if (maxReuqestSize < reqSize)
{
maxReuqestSize = reqSize;
maxReuqestApi = url;
}
totalRequestPacket += reqSize;
totalResponsePacket += byteSize;
totalElapsedTime += time;
}
public APITotalBoardEntity GetAPIStatusBoarder()
{
var boardEntity = new APITotalBoardEntity();
boardEntity.TotalRequestPacketSize = totalRequestPacket;
boardEntity.AverageRequestPacketSize = totalRequestPacket / apiData.Count;
boardEntity.TotalResponsePacketSize = totalResponsePacket;
boardEntity.AverageResponsePacketSize = totalResponsePacket / apiData.Count;
boardEntity.MaximumResponseTime = maxElapsedTime;
boardEntity.AverageResponseTime = totalElapsedTime / apiData.Count;
boardEntity.MaximumRequestPacketAPI = maxReuqestApi;
boardEntity.MaximumResponsePacketAPI = maxResponseApi;
boardEntity.MaximumResponseTimeAPI = maxResponseTimeApi;
return boardEntity;
//JsonUtility.ToJson()
}
public void UpdateEntity(string type, string data)
{
//Dcitionary 형으로 바꿈
JObject json = JObject.Parse(data);
foreach (JProperty prop in json.Children())
{
string key = prop.Name.ToString();
string value = prop.Value.ToString();
Debug.Log($"kEY : {key}, Value:{value}");
}
var datas = json["rows"].ToString();
JArray jarray = JArray.Parse(datas);
foreach (JObject obj in jarray.Children())
{
Dictionary<string, string> keyvalue = new();
int index = 0;
string id = string.Empty;
foreach (JProperty prop in obj.Children())
{
string key = prop.Name.ToString();
string value = prop.Value.ToString();
if (index == 0)
{
id = value;
index = 1;
}
keyvalue.Add(key, value);
}
DispatchMachineEvent(type, id, keyvalue);
}
}
private void DispatchMachineEvent(string type, string id, Dictionary<string, string> entity)
{
if (!listenerIdMap.ContainsKey(type))
{
Debug.LogError($"Key Value is missing!!!! -Key:{type}-");
}
if (listenerIdMap[type].ContainsKey(id))
{
listenerIdMap[type][id].Invoke(this, new StudioServiceTypeEventArgs(type, entity));
}
}
}
}