606 lines
24 KiB
C#
606 lines
24 KiB
C#
using Cysharp.Threading.Tasks;
|
|
using Newtonsoft.Json;
|
|
using SampleProject.Config;
|
|
using Simulator.Config;
|
|
using Simulator.Data;
|
|
using Simulator.Data.Transport;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UVC.Core;
|
|
using UVC.Data;
|
|
using UVC.Data.Core;
|
|
using UVC.Data.Mqtt;
|
|
using UVC.Factory;
|
|
using UVC.Network;
|
|
using UVC.Pool;
|
|
|
|
namespace Simulator.Data
|
|
{
|
|
public class ComponentsManager : SingletonScene<ComponentsManager>
|
|
{
|
|
private readonly Dictionary<string, string> prefabPaths = new Dictionary<string, string>()
|
|
{
|
|
{"source","prefabs/pallet"},
|
|
{"queue","prefabs/queue"},
|
|
{"rack","prefabs/rack"},
|
|
{"sink","prefabs/Sink_Container"},
|
|
{"asrs","prefabs/ASRS"},
|
|
{"robotArm","prefabs/RobotArm"},
|
|
{"processor","prefabs/Processor"},
|
|
{"worker","prefabs/Worker"}
|
|
};
|
|
|
|
Dictionary<string, ComponentBase> componentDatas = new Dictionary<string, ComponentBase>();
|
|
Dictionary<ComponentType, DataMapper> dataMapperDict = new Dictionary<ComponentType, DataMapper>();
|
|
|
|
private GameObjectPool<SourceComponent>? sourcePool;
|
|
private GameObjectPool<SinkComponent>? sinkPool;
|
|
private GameObjectPool<QueueComponent>? queuePool;
|
|
private GameObjectPool<RackComponent>? rackPool;
|
|
private GameObjectPool<ASRSComponent>? asrsPool;
|
|
private GameObjectPool<RobotArmComponent>? robotArmPool;
|
|
private GameObjectPool<ProcessorComponent>? processorPool;
|
|
private GameObjectPool<WorkerComponent>? workerPool;
|
|
|
|
public static LogicDetailData logicDetailData;
|
|
public static Webconfig webconfigData;
|
|
public SimulatorCodeDataClass codedata;
|
|
|
|
public event Action<string> onProjectNameRecieved;
|
|
public event Action<string> onUserNameRecieved;
|
|
|
|
public GameObjectPool<SourceComponent> SourcePool
|
|
{
|
|
get
|
|
{
|
|
if (sourcePool == null)
|
|
{
|
|
Debug.LogError("Pool is not initialized. Please call InitializePoolAsync first.");
|
|
}
|
|
return sourcePool!;
|
|
}
|
|
}
|
|
|
|
public GameObjectPool<SinkComponent> SinkPool
|
|
{
|
|
get
|
|
{
|
|
if (sourcePool == null)
|
|
{
|
|
Debug.LogError("Pool is not initialized. Please call InitializePoolAsync first.");
|
|
}
|
|
return sinkPool!;
|
|
}
|
|
}
|
|
|
|
public GameObjectPool<QueueComponent> QueuePool
|
|
{
|
|
get
|
|
{
|
|
if (queuePool == null)
|
|
{
|
|
Debug.LogError("Pool is not initialized. Please call InitializePoolAsync first.");
|
|
}
|
|
return queuePool!;
|
|
}
|
|
}
|
|
|
|
public GameObjectPool<RackComponent> RackPool
|
|
{
|
|
get
|
|
{
|
|
if (rackPool == null)
|
|
{
|
|
Debug.LogError("Pool is not initialized. Please call InitializePoolAsync first.");
|
|
}
|
|
return rackPool!;
|
|
}
|
|
}
|
|
|
|
public GameObjectPool<ASRSComponent> AsrsPool
|
|
{
|
|
get
|
|
{
|
|
if (asrsPool == null)
|
|
{
|
|
Debug.LogError("Pool is not initialized. Please call InitializePoolAsync first.");
|
|
}
|
|
return asrsPool!;
|
|
}
|
|
}
|
|
public GameObjectPool<RobotArmComponent> RobotArmPool
|
|
{
|
|
get
|
|
{
|
|
if (robotArmPool == null)
|
|
{
|
|
Debug.LogError("Pool is not initialized. Please call InitializePoolAsync first.");
|
|
}
|
|
return robotArmPool!;
|
|
}
|
|
}
|
|
|
|
public GameObjectPool<ProcessorComponent> ProcessorPool
|
|
{
|
|
get
|
|
{
|
|
if (processorPool == null)
|
|
{
|
|
Debug.LogError("Pool is not initialized. Please call InitializePoolAsync first.");
|
|
}
|
|
return processorPool!;
|
|
}
|
|
}
|
|
|
|
public GameObjectPool<WorkerComponent> WorkerPool
|
|
{
|
|
get
|
|
{
|
|
if (workerPool == null)
|
|
{
|
|
Debug.LogError("Pool is not initialized. Please call InitializePoolAsync first.");
|
|
}
|
|
return workerPool!;
|
|
}
|
|
}
|
|
|
|
protected override void Init()
|
|
{
|
|
InitializeSourcePoolAsync().ContinueWith(() =>
|
|
{
|
|
var sourceDataMask = new DataMask();
|
|
sourceDataMask.ObjectName = "Source"; // AGV 객체의 이름을 설정합니다.
|
|
sourceDataMask.ObjectIdKey = "component_id"; // AGV의 고유 식별자로 사용할 키를 설정합니다.
|
|
sourceDataMask["component_id"] = "";
|
|
sourceDataMask["event_name"] = "";
|
|
sourceDataMask["timestamp"] = new DateTime();
|
|
sourceDataMask["data"] = new DataMask()
|
|
{
|
|
["entity_ids"] = new List<string>(),
|
|
["total_entity"] = 0
|
|
};
|
|
|
|
DataMapper sourceMapper = new DataMapper(sourceDataMask);
|
|
dataMapperDict.Add(ComponentType.Source, sourceMapper);
|
|
});
|
|
InitializeSinkPoolAsync().ContinueWith(() =>
|
|
{
|
|
var sinkDataMask = new DataMask();
|
|
sinkDataMask.ObjectName = "Sink"; // AGV 객체의 이름을 설정합니다.
|
|
sinkDataMask.ObjectIdKey = "component_id"; // AGV의 고유 식별자로 사용할 키를 설정합니다.
|
|
sinkDataMask["component_id"] = "";
|
|
sinkDataMask["event_name"] = "";
|
|
sinkDataMask["timestamp"] = new DateTime();
|
|
sinkDataMask["data"] = new DataMask()
|
|
{
|
|
["entity_ids"] = new List<string>(),
|
|
};
|
|
|
|
DataMapper sinkmapper = new DataMapper(sinkDataMask);
|
|
dataMapperDict.Add(ComponentType.Sink, sinkmapper);
|
|
|
|
});
|
|
InitializeQueuePoolAsync().ContinueWith(() =>
|
|
{
|
|
dataMapperDict.Add(ComponentType.Queue, null);
|
|
});
|
|
InitializeRackPoolAsync().ContinueWith(() =>
|
|
{
|
|
var rackDataMask = new DataMask();
|
|
rackDataMask.ObjectName = "rack";
|
|
rackDataMask.ObjectIdKey = "component_id";
|
|
DataMapper rackmapper = new DataMapper(rackDataMask);
|
|
dataMapperDict.Add(ComponentType.Rack, rackmapper);
|
|
});
|
|
InitializeAsrsPoolAsync().ContinueWith(() =>
|
|
{
|
|
var asrsDataMask = new DataMask();
|
|
asrsDataMask.ObjectName = "asrs";
|
|
asrsDataMask.ObjectIdKey = "component_id";
|
|
DataMapper asrsmapper = new DataMapper(asrsDataMask);
|
|
dataMapperDict.Add(ComponentType.ASRS, asrsmapper);
|
|
});
|
|
InitializeRobotArmPoolAsync().ContinueWith(() =>
|
|
{
|
|
var robotArmDataMask = new DataMask();
|
|
robotArmDataMask.ObjectName = "RobotArm";
|
|
robotArmDataMask.ObjectIdKey = "component_id";
|
|
robotArmDataMask["component_id"] = "";
|
|
robotArmDataMask["event_name"] = "";
|
|
robotArmDataMask["timestamp"] = new DateTime();
|
|
robotArmDataMask["data"] = new DataMask()
|
|
{
|
|
["entity_id"] = "",
|
|
["processing_time"] = 0.0f,
|
|
["from"] = "",
|
|
["to"] = ""
|
|
};
|
|
DataMapper robotArmMapper = new DataMapper(robotArmDataMask);
|
|
dataMapperDict.Add(ComponentType.RobotArm, robotArmMapper);
|
|
});
|
|
InitializeProcessorPoolAsync().ContinueWith(() =>
|
|
{
|
|
var processorDataMask = new DataMask();
|
|
DataMapper processorMapper = new DataMapper(processorDataMask);
|
|
dataMapperDict.Add(ComponentType.Processor, processorMapper);
|
|
});
|
|
InitializeWorkerPoolAsync().ContinueWith(() =>
|
|
{
|
|
var workerDataMask = new DataMask();
|
|
DataMapper workermapper = new DataMapper(workerDataMask);
|
|
dataMapperDict.Add(ComponentType.Worker, workermapper);
|
|
});
|
|
//testRequest();
|
|
}
|
|
|
|
public async void testRequest()
|
|
{
|
|
var data = await HttpRequester.RequestGet<Totaljson>($"{Constants.HTTP_DOMAIN}/simulation/logics/{SimulationConfig.logicId}", null, null, true);
|
|
webconfigData = data.data.webConfig;
|
|
logicDetailData = data.data.data;
|
|
PathIndexer.Build(logicDetailData);
|
|
onProjectNameRecieved?.Invoke(data.data.name);
|
|
onUserNameRecieved?.Invoke(data.data.user.name);
|
|
SpawnComponents(data.data.data);
|
|
if (data.data.data.camAngle != null)
|
|
{
|
|
FactoryCameraController.Instance.SetCamera(data.data.data.camAngle);
|
|
}
|
|
if (logicDetailData.templates != null)
|
|
{
|
|
if (logicDetailData.templates.prefabs.Count >= 1)
|
|
{
|
|
PrefabManager.Instance.SetPrefabs(logicDetailData.templates.prefabs);
|
|
}
|
|
}
|
|
if (logicDetailData.transport_system != null)
|
|
{
|
|
if (logicDetailData.transport_system.node_networks != null && logicDetailData.transport_system.node_networks.Count >= 1)
|
|
{
|
|
foreach (var node_network in logicDetailData.transport_system.node_networks)
|
|
{
|
|
AGVNodeManager.Instance.SpawnNode(node_network.nodes);
|
|
AGVNodeManager.Instance.LinkNode(node_network.edges);
|
|
}
|
|
}
|
|
if (logicDetailData.transport_system.transport_managers != null && logicDetailData.transport_system.transport_managers.Count >= 1)
|
|
{
|
|
foreach (var transport_manager in logicDetailData.transport_system.transport_managers)
|
|
{
|
|
if (transport_manager.vehicle_fleets != null && transport_manager.vehicle_fleets.Count >= 1)
|
|
{
|
|
foreach (var vehicle in transport_manager.vehicle_fleets)
|
|
{
|
|
AGVManager.Instance.SpawnAGV(vehicle.vehicles, transport_manager.manager_type);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (logicDetailData.production_system.conveyors != null && logicDetailData.production_system.conveyors.Count >= 1)
|
|
{
|
|
ConveyorManager.Instance.Build(logicDetailData.production_system.conveyors);
|
|
}
|
|
}
|
|
|
|
public void SetMQTT(SimulatorCodeDataClass sdata)
|
|
{
|
|
codedata = sdata;
|
|
if (logicDetailData.transport_system != null)
|
|
{
|
|
if (logicDetailData.transport_system.transport_managers != null && logicDetailData.transport_system.transport_managers.Count >= 1)
|
|
{
|
|
foreach (var transport_manager in logicDetailData.transport_system.transport_managers)
|
|
{
|
|
if (transport_manager.vehicle_fleets != null && transport_manager.vehicle_fleets.Count >= 1)
|
|
{
|
|
foreach (var vehicle_fleet in transport_manager.vehicle_fleets)
|
|
{
|
|
AGVManager.Instance.InitAGV(vehicle_fleet.vehicles);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (logicDetailData.production_system.conveyors != null && logicDetailData.production_system.conveyors.Count >= 1)
|
|
{
|
|
foreach (var conveyor in logicDetailData.production_system.conveyors)
|
|
{
|
|
ConveyorManager.Instance.SubscribeConveyor(conveyor);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SubscribeTopic()
|
|
{
|
|
foreach (var componentdata in componentDatas)
|
|
{
|
|
DataRepository.Instance.MqttReceiver.AddTopic($"simulation/{SimulationConfig.SimulationCode}/components/+/{componentdata.Key}/#");
|
|
var mqttConfig = new MqttSubscriptionConfig($"simulation/{SimulationConfig.SimulationCode}/components/+/{componentdata.Key}/#",false);
|
|
mqttConfig.SetDataMapper(dataMapperDict[componentdata.Value.componentType]);
|
|
mqttConfig.SetHandler((value) => OnUpdateData(value, componentdata.Value.componentType));
|
|
DataRepository.Instance.MqttReceiver.Add(mqttConfig);
|
|
}
|
|
DataRepository.Instance.MqttReceiver.AddTopic($"simulation/{SimulationConfig.SimulationCode}/status_changed");
|
|
var Config = new MqttSubscriptionConfig($"simulation/{SimulationConfig.SimulationCode}/status_changed", false);
|
|
var progressDataMask = new DataMask();
|
|
DataMapper progressmapper = new DataMapper(progressDataMask);
|
|
Config.SetDataMapper(progressmapper);
|
|
Config.SetHandler(PlayerPropertyDataBase.Instance.GetMqttData);
|
|
DataRepository.Instance.MqttReceiver.Add(Config);
|
|
}
|
|
|
|
public void OnUpdateData(IDataObject data, ComponentType type)
|
|
{
|
|
if (data == null) return;
|
|
|
|
DataObject? obj = data as DataObject;
|
|
if (obj == null) return;
|
|
|
|
switch (type)
|
|
{
|
|
case ComponentType.Source:
|
|
if (string.Equals(obj.GetString("event_name"), "completed"))
|
|
{
|
|
SourceComponent? source = sourcePool.GetItem(obj.GetString("component_id")!);
|
|
source.GetModelData(obj);
|
|
}
|
|
break;
|
|
case ComponentType.Sink:
|
|
if (string.Equals(obj.GetString("event_name"), "completed"))
|
|
{
|
|
SinkComponent? sink = sinkPool.GetItem(obj.GetString("component_id")!);
|
|
sink.GetModelData(obj);
|
|
}
|
|
break;
|
|
case ComponentType.Queue:
|
|
if (string.Equals(obj.GetString("event_name"), "completed"))
|
|
{
|
|
QueueComponent? queue = QueuePool.GetItem(obj.GetString("component_id")!);
|
|
queue.GetModelData(obj);
|
|
}
|
|
break;
|
|
case ComponentType.Rack:
|
|
if (string.Equals(obj.GetString("event_name"), "entity_stored"))
|
|
{
|
|
RackComponent? rack = rackPool.GetItem(obj.GetString("component_id")!);
|
|
rack.GetModelData(obj);
|
|
}
|
|
if (string.Equals(obj.GetString("event_name"), "inventory_initialized"))
|
|
{
|
|
RackComponent? rack = rackPool.GetItem(obj.GetString("component_id")!);
|
|
rack.InitializeQueue(obj);
|
|
}
|
|
break;
|
|
case ComponentType.ASRS:
|
|
ASRSComponent? asrs = asrsPool.GetItem(obj.GetString("component_id")!);
|
|
asrs.GetModelData(obj);
|
|
break;
|
|
case ComponentType.RobotArm:
|
|
RobotArmComponent? robotArm = robotArmPool.GetItem(obj.GetString("component_id")!);
|
|
robotArm.GetModelData(obj);
|
|
break;
|
|
case ComponentType.Processor:
|
|
ProcessorComponent? processor = processorPool.GetItem(obj.GetString("component_id")!);
|
|
processor.GetModelData(obj);
|
|
break;
|
|
case ComponentType.Worker:
|
|
WorkerComponent? worker = workerPool.GetItem(obj.GetString("component_id")!);
|
|
worker.GetModelData(obj);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private async UniTask InitializeSourcePoolAsync()
|
|
{
|
|
if (sourcePool != null) return;
|
|
|
|
var prefab = await Resources.LoadAsync<GameObject>(prefabPaths["source"]) as GameObject;
|
|
if (prefab == null)
|
|
{
|
|
Debug.LogError($"Prefab not found at path: {prefabPaths["source"]}");
|
|
return;
|
|
}
|
|
sourcePool = new GameObjectPool<SourceComponent>(prefab, transform);
|
|
}
|
|
|
|
private async UniTask InitializeSinkPoolAsync()
|
|
{
|
|
if (sinkPool != null) return;
|
|
|
|
var prefab = await Resources.LoadAsync<GameObject>(prefabPaths["sink"]) as GameObject;
|
|
if (prefab == null)
|
|
{
|
|
Debug.LogError($"Prefab not found at path: {prefabPaths["sink"]}");
|
|
return;
|
|
}
|
|
sinkPool = new GameObjectPool<SinkComponent>(prefab, transform);
|
|
}
|
|
|
|
private async UniTask InitializeQueuePoolAsync()
|
|
{
|
|
if (queuePool != null) return;
|
|
|
|
var prefab = await Resources.LoadAsync<GameObject>(prefabPaths["queue"]) as GameObject;
|
|
if (prefab == null)
|
|
{
|
|
Debug.LogError($"Prefab not found at path: {prefabPaths["queue"]}");
|
|
return;
|
|
}
|
|
queuePool = new GameObjectPool<QueueComponent>(prefab, transform);
|
|
}
|
|
|
|
private async UniTask InitializeRackPoolAsync()
|
|
{
|
|
if (rackPool != null) return;
|
|
|
|
var prefab = await Resources.LoadAsync<GameObject>(prefabPaths["rack"]) as GameObject;
|
|
if (prefab == null)
|
|
{
|
|
Debug.LogError($"Prefab not found at path: {prefabPaths["rack"]}");
|
|
return;
|
|
}
|
|
rackPool = new GameObjectPool<RackComponent>(prefab, transform);
|
|
}
|
|
|
|
private async UniTask InitializeAsrsPoolAsync()
|
|
{
|
|
if (asrsPool != null) return;
|
|
|
|
var prefab = await Resources.LoadAsync<GameObject>(prefabPaths["asrs"]) as GameObject;
|
|
if (prefab == null)
|
|
{
|
|
Debug.LogError($"Prefab not found at path: {prefabPaths["asrs"]}");
|
|
return;
|
|
}
|
|
asrsPool = new GameObjectPool<ASRSComponent>(prefab, transform);
|
|
}
|
|
|
|
private async UniTask InitializeRobotArmPoolAsync()
|
|
{
|
|
if (robotArmPool != null) return;
|
|
|
|
var prefab = await Resources.LoadAsync<GameObject>(prefabPaths["robotArm"]) as GameObject;
|
|
if (prefab == null)
|
|
{
|
|
Debug.LogError($"Prefab not found at path: {prefabPaths["robotArm"]}");
|
|
return;
|
|
}
|
|
robotArmPool = new GameObjectPool<RobotArmComponent>(prefab, transform);
|
|
}
|
|
|
|
private async UniTask InitializeProcessorPoolAsync()
|
|
{
|
|
if (processorPool != null) return;
|
|
|
|
var prefab = await Resources.LoadAsync<GameObject>(prefabPaths["processor"]) as GameObject;
|
|
if (prefab == null)
|
|
{
|
|
Debug.LogError($"Prefab not found at path: {prefabPaths["processor"]}");
|
|
return;
|
|
}
|
|
processorPool = new GameObjectPool<ProcessorComponent>(prefab, transform);
|
|
}
|
|
|
|
private async UniTask InitializeWorkerPoolAsync()
|
|
{
|
|
if (workerPool != null) return;
|
|
|
|
var prefab = await Resources.LoadAsync<GameObject>(prefabPaths["worker"]) as GameObject;
|
|
if (prefab == null)
|
|
{
|
|
Debug.LogError($"Prefab not found at path: {prefabPaths["worker"]}");
|
|
return;
|
|
}
|
|
workerPool = new GameObjectPool<WorkerComponent>(prefab, transform);
|
|
}
|
|
|
|
private void SpawnComponents(LogicDetailData data)
|
|
{
|
|
if (data.production_system != null)
|
|
{
|
|
if (data.production_system.sources != null)
|
|
{
|
|
foreach (var component in data.production_system.sources)
|
|
{
|
|
var source = sourcePool.GetItem($"{component.name}");
|
|
source.componentType = ComponentType.Source;
|
|
source.SetComponent(component);
|
|
//source.SetPosition();
|
|
componentDatas.Add(component.name, source);
|
|
}
|
|
}
|
|
if (data.production_system.sinks != null)
|
|
{
|
|
foreach (var component in data.production_system.sinks)
|
|
{
|
|
var sink = sinkPool.GetItem($"{component.name}");
|
|
sink.componentType = ComponentType.Sink;
|
|
sink.SetComponent(component);
|
|
//sink.SetPosition();
|
|
componentDatas.Add(component.name, sink);
|
|
}
|
|
}
|
|
if (data.production_system.racks != null)
|
|
{
|
|
foreach (var component in data.production_system.racks)
|
|
{
|
|
var rack = rackPool.GetItem($"{component.name}");
|
|
rack.componentType = ComponentType.Rack;
|
|
rack.SetComponent(component);
|
|
//rack.SetPosition();
|
|
componentDatas.Add(component.name, rack);
|
|
}
|
|
}
|
|
if (data.production_system.asrs != null)
|
|
{
|
|
foreach (var component in data.production_system.asrs)
|
|
{
|
|
var asrs = asrsPool.GetItem($"{component.name}");
|
|
asrs.componentType = ComponentType.ASRS;
|
|
asrs.SetComponent(component);
|
|
//asrs.SetPosition();
|
|
componentDatas.Add(component.name, asrs);
|
|
}
|
|
}
|
|
if (data.production_system.robot_arms != null)
|
|
{
|
|
foreach (var component in data.production_system.robot_arms)
|
|
{
|
|
var robotArm = robotArmPool.GetItem($"{component.name}");
|
|
robotArm.componentType = ComponentType.RobotArm;
|
|
robotArm.SetComponent(component);
|
|
//robotArm.SetPosition();
|
|
componentDatas.Add(component.name, robotArm);
|
|
}
|
|
}
|
|
if (data.production_system.processors != null)
|
|
{
|
|
foreach (var component in data.production_system.processors)
|
|
{
|
|
var processor = processorPool.GetItem($"{component.name}");
|
|
processor.componentType = ComponentType.Processor;
|
|
processor.SetComponent(component);
|
|
//processor.SetPosition();
|
|
componentDatas.Add(component.name, processor);
|
|
}
|
|
}
|
|
}
|
|
if (data.infrastructure != null)
|
|
{
|
|
if (data.infrastructure.queues != null)
|
|
{
|
|
foreach (var component in data.infrastructure.queues)
|
|
{
|
|
var queue = queuePool.GetItem($"{component.name}");
|
|
queue.componentType = ComponentType.Queue;
|
|
queue.SetComponent(component);
|
|
//queue.SetPosition();
|
|
componentDatas.Add(component.name, queue);
|
|
}
|
|
}
|
|
if (data.infrastructure.resources != null)
|
|
{
|
|
foreach (var component in data.infrastructure.resources)
|
|
{
|
|
var worker = workerPool.GetItem($"{component.name}");
|
|
worker.componentType = ComponentType.Worker;
|
|
worker.SetComponent(component);
|
|
//worker.SetPosition();
|
|
componentDatas.Add(component.name, worker);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public ComponentBase GetComponentData(string name)
|
|
{
|
|
if (componentDatas.ContainsKey(name))
|
|
{
|
|
return componentDatas[name];
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
} |