295 lines
9.9 KiB
C#
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));
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|