#nullable enable using Factory; using System; using System.Collections.Generic; using UnityEngine; using UVC.Core; using UVC.Data; using UVC.Data.Core; using UVC.Data.Mqtt; namespace UVC.Factory.Component { public class PortManager : SingletonScene { public Action? OnCreated; private bool created = false; public bool Created => created; private Dictionary ports = new Dictionary(); /// /// 초기화 메서드입니다. /// Awake 메서드에서 호출되며, MonoBehaviour가 생성될 때 한 번만 실행됩니다. /// protected override void Init() { //playback에서도 데이터를 업데이트 하기에 DataRepository에 핸들러를 추가합니다. DataRepository.Instance.AddDataUpdateHandler("PORT", OnUpdateData); var mqttConfig = new MqttSubscriptionConfig("PORT"); mqttConfig.SetDataMapper(new DataMapper(new DataMask { ObjectIdKey = "PORT_ID", ObjectName = "PORTNAME" })); // 생성한 파이프라인 정보를 전역 MQTT 파이프라인에 추가합니다. DataRepository.Instance.MqttReceiver.Add(mqttConfig); FactorySceneMain.Instance.Initialized += OnSceneInitialized; } /// /// 씬이 완전히 초기화된 후 호출됩니다. /// private void OnSceneInitialized() { } public void AddPort(string name, Port port) { if (port == null || string.IsNullOrEmpty(name)) { Debug.LogError("포트가 유효하지 않습니다."); return; } if (ports.ContainsKey(name)) { Debug.LogWarning($"포트 ID {name}가 이미 존재합니다. 덮어쓰지 않습니다."); return; } ports[name] = port; //Debug.Log($"포트 {name}가 추가되었습니다."); } /// /// 데이터 수신 시 호출되는 공개 핸들러입니다. /// 수신된 AGV 데이터 배열을 비동기적으로 처리하여 씬에 반영합니다. /// 추가, 제거, 수정된 AGV 데이터를 각각 구분하여 처리합니다. /// /// 수신된 데이터 객체 (DataArray 형태) public void OnUpdateData(IDataObject data) { //Debug.Log($"PORTManager OnUpdateData data == null:{data == null}"); if (data == null) return; DataArray? arr = data as DataArray; if (arr == null || arr.Count == 0) return; // 데이터 배열에서 추가, 제거, 수정된 항목 리스트를 가져옵니다. var AddedItems = arr.AddedItems; var RemovedItems = arr.RemovedItems; var ModifiedList = arr.ModifiedList; var portsIds = new HashSet(ports.Keys); //Debug.Log($"PORTManager received data: ports:{ports.Count} portsIds:{portsIds.Count} count:{arr.Count}, Added={AddedItems.Count}, Removed={RemovedItems.Count}, Modified={ModifiedList.Count}"); // 추가된 항목 처리 foreach (var item in AddedItems) { if (item != null) { string? portId = item.GetString("PORT_ID"); if (portId == null) continue; if (ports.ContainsKey(portId)) { Port port = ports[portId]; port.Info = new FactoryObjectInfo( //item.GetString("PORTNAME"), item.GetString("PORT_ID"), item.GetString("PORT_ID"), port.areaType.ToString(), port.areaType.ToString(), port.transform.parent.name, "PORT" ); port.UpdateData(item); } } } // 수정된 항목 처리 foreach (var item in ModifiedList) { if (item != null) { string? portId = item.GetString("PORT_ID"); if (portId == null) continue; if (ports.ContainsKey(portId)) { ports[portId].UpdateData(item); } } } if (created == false) { created = true; // 씬이 처음 초기화될 때 PORTManager가 생성되었음을 알립니다. Debug.Log("PORTManager created and initialized."); OnCreated?.Invoke(); } } } }