#nullable enable using NUnit.Framework; using System; using System.Collections.Generic; using UVC.Data.Core; namespace UVC.Data.Mqtt { /// /// 수신된 단일 MQTT 메시지에 대한 모든 정보를 담는 데이터 컨테이너 클래스입니다. /// 이 객체는 MqttWorker가 메시지를 수신했을 때 생성되며, MqttDataManager를 통해 /// 최종적으로 데이터 소비자에게 전달됩니다. /// /// /// /// // MqttDataPacket 객체 생성 예시 /// var packet = new MqttDataPacket("sensor/temp", "25.5"); /// /// // 데이터 접근 예시 /// Debug.Log($"수신 시간: {packet.Timestamp}"); /// Debug.Log($"토픽: {packet.Topic}"); /// Debug.Log($"내용: {packet.Payload}"); /// /// // MqttDataManager가 이 패킷을 리스너에게 전달한 후, /// // IsPropagated를 true로 설정하여 중복 전송을 방지합니다. /// packet.IsPropagated = true; /// Debug.Log($"처리 완료 여부: {packet.IsPropagated}"); /// /// public class MqttDataPacket { public bool IsInPool { get; set; } = false; /// /// 데이터가 수신된 시간 (UTC 기준)입니다. /// 전 세계 어디서든 동일한 시간 기록을 보장하기 위해 협정 세계시(UTC)를 사용합니다. /// 'init' 키워드는 객체가 처음 생성될 때만 값을 할당할 수 있도록 하여, 데이터의 불변성을 보장합니다. /// public DateTime Timestamp { get; private set; } /// /// 메시지가 발행된 MQTT 토픽입니다. (예: "home/livingroom/light") /// public string Topic { get; private set; } /// /// 메시지의 실제 내용(데이터)입니다. 보통 JSON 형식의 문자열이 담깁니다. /// public string Payload { get; private set; } /// /// 이 데이터가 리스너에게 전파(전달)되었는지 여부를 나타내는 플래그입니다. /// MqttDataManager가 이 값을 사용하여 동일한 데이터를 중복으로 전달하는 것을 방지합니다. /// public bool IsPropagated { get; set; } = false; public MqttDataPacket() { // 기본 생성자 - 빈 객체 생성 시 사용 this.Timestamp = DateTime.UtcNow; this.Topic = string.Empty; this.Payload = string.Empty; this.IsPropagated = false; } /// /// DataObject 객체로부터 MqttDataPacket 인스턴스를 생성합니다. /// TIMESTAMP 필드를 파싱하여 타임스탬프로 사용합니다. /// /// 메시지가 수신된 토픽 /// JSON 데이터를 담고 있는 DataObject public MqttDataPacket(string topic, DataObject dataObject) { this.Topic = topic; this.Payload = dataObject.ToJson(); this.IsPropagated = false; // TIMESTAMP 필드에서 시간 값을 파싱합니다. 실패 시 현재 UTC 시간을 사용합니다. var timestampStr = dataObject.GetString("TIMESTAMP"); if (!string.IsNullOrEmpty(timestampStr) && DateTime.TryParse(timestampStr, null, System.Globalization.DateTimeStyles.AdjustToUniversal, out var parsedTimestamp)) { this.Timestamp = parsedTimestamp; } else { this.Timestamp = DateTime.UtcNow; } } /// /// 토픽과 JSON 페이로드를 포함하는 MQTT 통신용 데이터 패킷을 나타냅니다. /// /// 클래스는 MQTT 메시지의 토픽과 페이로드를 캡슐화하는 데 사용됩니다. /// 타임스탬프 및 전파 상태와 같은 메타데이터도 함께 캡슐화합니다. 매개변수는 올바른 사용을 위해 유효한 문자열이어야 합니다. /// /// MQTT 메시지와 연결된 토픽입니다. null이거나 비어 있을 수 없습니다. /// MQTT 메시지의 JSON 페이로드입니다. null이거나 비어 있을 수 없습니다. public MqttDataPacket(string topic, string json) { this.Topic = topic; this.Payload = json; this.IsPropagated = false; this.Timestamp = DateTime.UtcNow; } /// /// DataObject 객체로부터 MqttDataPacket 인스턴스를 설정합니다. /// TIMESTAMP 필드를 파싱하여 타임스탬프로 사용합니다. /// /// 메시지가 수신된 토픽 /// JSON 데이터를 담고 있는 DataObject public MqttDataPacket FromDataObject(string topic, DataObject dataObject) { this.Topic = topic; this.Payload = dataObject.ToJson(); this.IsPropagated = false; // TIMESTAMP 필드에서 시간 값을 파싱합니다. 실패 시 현재 UTC 시간을 사용합니다. var timestampStr = dataObject.GetString("TIMESTAMP"); if (!string.IsNullOrEmpty(timestampStr) && DateTime.TryParse(timestampStr, null, System.Globalization.DateTimeStyles.AdjustToUniversal, out var parsedTimestamp)) { this.Timestamp = parsedTimestamp; } else { this.Timestamp = DateTime.UtcNow; } return this; } /// /// DataObject 객체로부터 MqttDataPacket 인스턴스를 설정합니다. /// TIMESTAMP 필드를 파싱하여 타임스탬프로 사용합니다. /// /// 메시지가 수신된 토픽 /// MQTT 메시지의 JSON 페이로드입니다. null이거나 비어 있을 수 없습니다. public MqttDataPacket FromJson(string topic, string json) { this.Topic = topic; this.Payload = json; this.IsPropagated = false; this.Timestamp = DateTime.UtcNow; return this; } /// /// 객체를 초기 상태로 재설정합니다. /// /// 이 메서드는 를 현재 UTC 시간으로 설정하고, 문자열을 지우고, 로 설정합니다. public void Reset() { // 객체를 초기 상태로 재설정합니다. this.Timestamp = DateTime.UtcNow; this.Topic = string.Empty; this.Payload = string.Empty; this.IsPropagated = false; } /// /// 재사용을 위해 현재 인스턴스를 풀로 반환합니다. /// /// 이 메서드는 인스턴스가 더 이상 필요하지 않을 때 호출해야 하며, 이를 통해 인스턴스를 재사용하고 /// 새 인스턴스를 생성하는 오버헤드를 줄일 수 있습니다. 인스턴스를 풀로 반환하기 전에 /// 인스턴스가 유효한 상태인지 확인하십시오. public void ReturnToPool() { MqttDataPacketPool.Return(this); } /// /// 객체 목록을 JSON 배열 문자열로 변환합니다. /// /// 변환할 객체 목록입니다. null일 수 없습니다. /// 제공된 패킷의 페이로드를 나타내는 JSON 배열 문자열입니다. 목록이 비어 있거나 null이면 "[]"를 반환합니다. /// public static string ToJsonFromList(List packets) { if (packets == null || packets.Count == 0) return "[]"; bool isObject = packets.Count == 1 && packets[0].Payload.Trim().StartsWith("{"); if (isObject) { return packets[0].Payload; } var jsonArray = new System.Text.StringBuilder("["); for (int i = 0; i < packets.Count; i++) { var packet = packets[i]; jsonArray.Append(packet.Payload); if (i < packets.Count - 1) { jsonArray.Append(","); } } jsonArray.Append("]"); return jsonArray.ToString(); } } }