167 lines
7.1 KiB
C#
167 lines
7.1 KiB
C#
#nullable enable
|
|
using NUnit.Framework;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UVC.Data.Core;
|
|
|
|
namespace UVC.Data.Mqtt
|
|
{
|
|
/// <summary>
|
|
/// 수신된 단일 MQTT 메시지에 대한 모든 정보를 담는 데이터 컨테이너 클래스입니다.
|
|
/// 이 객체는 MqttWorker가 메시지를 수신했을 때 생성되며, MqttDataManager를 통해
|
|
/// 최종적으로 데이터 소비자에게 전달됩니다.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// // 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}");
|
|
/// </code>
|
|
/// </example>
|
|
public class MqttDataPacket
|
|
{
|
|
|
|
public bool IsInPool { get; set; } = false;
|
|
|
|
/// <summary>
|
|
/// 데이터가 수신된 시간 (UTC 기준)입니다.
|
|
/// 전 세계 어디서든 동일한 시간 기록을 보장하기 위해 협정 세계시(UTC)를 사용합니다.
|
|
/// 'init' 키워드는 객체가 처음 생성될 때만 값을 할당할 수 있도록 하여, 데이터의 불변성을 보장합니다.
|
|
/// </summary>
|
|
public DateTime Timestamp { get; private set; }
|
|
|
|
/// <summary>
|
|
/// 메시지가 발행된 MQTT 토픽입니다. (예: "home/livingroom/light")
|
|
/// </summary>
|
|
public string Topic { get; private set; }
|
|
|
|
/// <summary>
|
|
/// 메시지의 실제 내용(데이터)입니다. 보통 JSON 형식의 문자열이 담깁니다.
|
|
/// </summary>
|
|
public string Payload { get; private set; }
|
|
|
|
/// <summary>
|
|
/// 이 데이터가 리스너에게 전파(전달)되었는지 여부를 나타내는 플래그입니다.
|
|
/// MqttDataManager가 이 값을 사용하여 동일한 데이터를 중복으로 전달하는 것을 방지합니다.
|
|
/// </summary>
|
|
public bool IsPropagated { get; set; } = false;
|
|
|
|
public MqttDataPacket()
|
|
{
|
|
// 기본 생성자 - 빈 객체 생성 시 사용
|
|
this.Timestamp = DateTime.UtcNow;
|
|
this.Topic = string.Empty;
|
|
this.Payload = string.Empty;
|
|
this.IsPropagated = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// DataObject 객체로부터 MqttDataPacket 인스턴스를 생성합니다.
|
|
/// TIMESTAMP 필드를 파싱하여 타임스탬프로 사용합니다.
|
|
/// </summary>
|
|
/// <param name="topic">메시지가 수신된 토픽</param>
|
|
/// <param name="dataObject">JSON 데이터를 담고 있는 DataObject</param>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// DataObject 객체로부터 MqttDataPacket 인스턴스를 설정합니다.
|
|
/// TIMESTAMP 필드를 파싱하여 타임스탬프로 사용합니다.
|
|
/// </summary>
|
|
/// <param name="topic">메시지가 수신된 토픽</param>
|
|
/// <param name="dataObject">JSON 데이터를 담고 있는 DataObject</param>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 객체를 초기 상태로 재설정합니다.
|
|
/// </summary>
|
|
/// <remarks>이 메서드는 <see cref="Timestamp"/>를 현재 UTC 시간으로 설정하고, <see
|
|
/// cref="Topic"/> 및 <see cref="Payload"/> 문자열을 지우고, <see cref="IsPropagated"/>를 <see
|
|
/// langword="false"/>로 설정합니다.</remarks>
|
|
public void Reset()
|
|
{
|
|
// 객체를 초기 상태로 재설정합니다.
|
|
this.Timestamp = DateTime.UtcNow;
|
|
this.Topic = string.Empty;
|
|
this.Payload = string.Empty;
|
|
this.IsPropagated = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 재사용을 위해 현재 인스턴스를 풀로 반환합니다.
|
|
/// </summary>
|
|
/// <remarks>이 메서드는 인스턴스가 더 이상 필요하지 않을 때 호출해야 하며, 이를 통해 인스턴스를 재사용하고
|
|
/// 새 인스턴스를 생성하는 오버헤드를 줄일 수 있습니다. 인스턴스를 풀로 반환하기 전에
|
|
/// 인스턴스가 유효한 상태인지 확인하십시오.</remarks>
|
|
public void ReturnToPool()
|
|
{
|
|
MqttDataPacketPool.Return(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// <see cref="MqttDataPacket"/> 객체 목록을 JSON 배열 문자열로 변환합니다.
|
|
/// </summary>
|
|
/// <param name="packets">변환할 <see cref="MqttDataPacket"/> 객체 목록입니다. null일 수 없습니다.</param>
|
|
/// <returns>제공된 패킷의 페이로드를 나타내는 JSON 배열 문자열입니다. 목록이 비어 있거나 null이면 "[]"를 반환합니다.
|
|
///</returns>
|
|
public static string ToJsonFromList(List<MqttDataPacket> packets)
|
|
{
|
|
if (packets == null || packets.Count == 0) return "[]";
|
|
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();
|
|
}
|
|
|
|
}
|
|
}
|