diff --git a/Assets/Scripts/UVC/Data/HttpPipeLine.cs b/Assets/Scripts/UVC/Data/HttpPipeLine.cs
index a04a9c08..01ca8362 100644
--- a/Assets/Scripts/UVC/Data/HttpPipeLine.cs
+++ b/Assets/Scripts/UVC/Data/HttpPipeLine.cs
@@ -227,11 +227,24 @@ namespace UVC.Data
}
IDataObject? dataObject = null;
+ result = result.Trim();
+
if (!string.IsNullOrEmpty(result))
{
- result = result.Trim();
try
{
+ string? responseData = info.ResponseMask.Apply(result);
+ // responseData가 null인 경우는 올바른 응답이 아니므로 처리하지 않음
+ if (responseData == null)
+ {
+ throw new Exception($"유효하지 않은 response data. {result}");
+ }
+ else
+ {
+ result = responseData.Trim();
+ }
+
+
if (result.StartsWith("{"))
{
if (info.DataMapper != null)
diff --git a/Assets/Scripts/UVC/Data/HttpPipeLineInfo.cs b/Assets/Scripts/UVC/Data/HttpPipeLineInfo.cs
index 7c7fb204..220fa9d4 100644
--- a/Assets/Scripts/UVC/Data/HttpPipeLineInfo.cs
+++ b/Assets/Scripts/UVC/Data/HttpPipeLineInfo.cs
@@ -1,5 +1,6 @@
#nullable enable
+using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
@@ -34,6 +35,7 @@ namespace UVC.Data
private int _repeatCount = 0; // 반복 횟수, 0은 무한 반복
private int _repeatInterval = 1000; // 반복 간격 (ms)
private DataMapper? _dataMapper = null; // 데이터 매퍼
+ private ResponseMask _responseMask = new ResponseMask(); // response 데이터 성공 여부와 데이터를 구분하는 마스크
private int _maxRetryCount = 3;
private int _retryDelay = 1000; // 밀리초
private bool _updatedDataOnly = false; // 업데이트된 데이터만 받을 여부
@@ -83,6 +85,11 @@ namespace UVC.Data
///
public DataMapper? DataMapper => _dataMapper;
+ ///
+ /// response에 적용되는 데이터 마스크
+ ///
+ public ResponseMask ResponseMask => _responseMask;
+
///
/// 최대 재시도 횟수
///
@@ -125,6 +132,17 @@ namespace UVC.Data
return this;
}
+ ///
+ /// HTTP 파이프라인에 적용할 response 마스크를 설정하고 업데이트된 파이프라인 구성을 반환합니다.
+ ///
+ /// HTTP response에 적용할 입니다.
+ /// 지정된 response 마스크가 적용된 업데이트된 인스턴스입니다.
+ public HttpPipeLineInfo setResponseMask(ResponseMask responseMask)
+ {
+ _responseMask = responseMask;
+ return this;
+ }
+
///
/// HTTP 요청이 완료된 후 호출될 핸들러를 설정합니다.
/// 변경 된 데이터는 IDataObject로 전달됩니다.
@@ -186,4 +204,41 @@ namespace UVC.Data
}
}
+
+ public class ResponseMask
+ {
+ private string successKey = "message";
+ private string successValue = "success";
+ private string dataKey = "data";
+
+ public string SuccessKey { get; }
+ public string SuccessValue { get; }
+ public string DataKey { get; }
+
+ public ResponseMask() { }
+
+ public ResponseMask(string successKey, string successValue, string dataKey)
+ {
+ this.successKey = successKey;
+ this.successValue = successValue;
+ this.dataKey = dataKey;
+ }
+
+
+ public string? Apply(string response)
+ {
+ JObject responseObject = JObject.Parse(response);
+ if(responseObject.TryGetValue(successKey, out JToken? successToken) &&
+ responseObject.TryGetValue(dataKey, out JToken? dataToken) &&
+ successToken?.ToString().ToLower() == successValue)
+ {
+ // 성공적인 응답 처리 로직
+ return dataToken?.ToString(); // 실제로는 dataKey에 해당하는 데이터만 반환할 수 있습니다.
+ }
+ else
+ {
+ return null; // 실패한 응답 처리 로직
+ }
+ }
+ }
}
diff --git a/Assets/Scripts/UVC/Data/MQTTPipeLine.cs b/Assets/Scripts/UVC/Data/MQTTPipeLine.cs
index 862b3777..6d00136a 100644
--- a/Assets/Scripts/UVC/Data/MQTTPipeLine.cs
+++ b/Assets/Scripts/UVC/Data/MQTTPipeLine.cs
@@ -2,7 +2,9 @@
using Newtonsoft.Json.Linq;
using SampleProject.Config;
+using System;
using System.Collections.Generic;
+using UVC.Log;
using UVC.network;
using UVC.Tests;
@@ -135,30 +137,41 @@ namespace UVC.Data
{
MQTTPipeLineInfo info = infoList[topic];
IDataObject? dataObject = null;
+
+ message = message.Trim();
if (!string.IsNullOrEmpty(message))
{
- message = message.Trim();
- if (message.StartsWith("{"))
+ try
{
- JObject source = JObject.Parse(message);
- if (info.DataMapper != null) dataObject = info.DataMapper.Map(source);
+ if (message.StartsWith("{"))
+ {
+ JObject source = JObject.Parse(message);
+ if (info.DataMapper != null) dataObject = info.DataMapper.Map(source);
+ }
+ else if (message.StartsWith("["))
+ {
+ JArray source = JArray.Parse(message);
+ if (info.DataMapper != null) dataObject = info.DataMapper.Map(source);
+ }
+
+ if (dataObject != null) dataObject = DataRepository.Instance.AddData(topic, dataObject, info.UpdatedDataOnly);
+
+ // 갱신 된 데이터가 있는 경우 핸들러 호출
+ if (info.UpdatedDataOnly)
+ {
+ if (dataObject != null && dataObject.UpdatedCount > 0) info.Handler?.Invoke(dataObject);
+ }
+ else
+ {
+ info.Handler?.Invoke(dataObject);
+ }
}
- else if (message.StartsWith("["))
+ catch (Exception ex)
{
- JArray source = JArray.Parse(message);
- if (info.DataMapper != null) dataObject = info.DataMapper.Map(source);
+ // 예외 발생 시 로깅 또는 처리
+ ULog.Error($"Error processing message for topic '{topic}': {ex.Message}", ex);
}
}
- if (dataObject != null) dataObject = DataRepository.Instance.AddData(topic, dataObject, info.UpdatedDataOnly);
- // 갱신 된 데이터가 있는 경우 핸들러 호출
- if (info.UpdatedDataOnly)
- {
- if (dataObject != null && dataObject.UpdatedCount > 0) info.Handler?.Invoke(dataObject);
- }
- else
- {
- info.Handler?.Invoke(dataObject);
- }
}
}
diff --git a/Assets/Scripts/UVC/Network/MQTTService.cs b/Assets/Scripts/UVC/Network/MQTTService.cs
index f17f4936..d936191d 100644
--- a/Assets/Scripts/UVC/Network/MQTTService.cs
+++ b/Assets/Scripts/UVC/Network/MQTTService.cs
@@ -323,11 +323,13 @@ namespace UVC.network
string payload = Encoding.UTF8.GetString(message.Payload.Data, message.Payload.Offset, message.Payload.Count);
ULog.Debug($"MQTT OnTopic {topic.Filter.OriginalFilter} => {payload}");
ServerLog.LogMqtt(MQTTDomain, MQTTPort.ToString(), topic.Filter.OriginalFilter, payload, DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"));
-
- if(topicHandler.TryGetValue(topic.Filter.OriginalFilter, out var handler))
+ if(payload.Trim().Length > 0)
{
- // 등록된 핸들러가 있으면 호출
- handler.Invoke(topic.Filter.OriginalFilter, payload);
+ if (topicHandler.TryGetValue(topic.Filter.OriginalFilter, out var handler))
+ {
+ // 등록된 핸들러가 있으면 호출
+ handler.Invoke(topic.Filter.OriginalFilter, payload);
+ }
}
}
diff --git a/Assets/Scripts/UVC/Tests/Data/HttpPipeLineTests.cs b/Assets/Scripts/UVC/Tests/Data/HttpPipeLineTests.cs
index 94b0d73d..13a41da0 100644
--- a/Assets/Scripts/UVC/Tests/Data/HttpPipeLineTests.cs
+++ b/Assets/Scripts/UVC/Tests/Data/HttpPipeLineTests.cs
@@ -222,7 +222,7 @@ namespace UVC.Tests.Data
bool handlerCalled = false;
DataObject? receivedData = null;
- var mockResponse = @"{""name"": ""테스트"", ""value"": 123}";
+ var mockResponse = @"{""message"": ""Success"", ""data"": {""name"": ""테스트"", ""value"": 123}}";
// DataMask와 DataMapper 설정
var dataMask = new DataMask();
@@ -277,7 +277,7 @@ namespace UVC.Tests.Data
bool handlerCalled = false;
IDataObject? receivedData = null;
- var mockResponse = @"[{""name"": ""항목1"", ""value"": 10}, {""name"": ""항목2"", ""value"": 20}]";
+ var mockResponse = @"{""message"": ""Success"", ""data"": [{""name"": ""항목1"", ""value"": 10}, {""name"": ""항목2"", ""value"": 20}]}";
// 배열용 DataMask 설정
var dataMask = new DataMask
@@ -701,9 +701,9 @@ namespace UVC.Tests.Data
// 여러 응답을 순차적으로 반환하기 위한 응답 데이터 설정
string[] mockResponses = new string[]
{
- @"{""id"": 1, ""status"": ""pending"", ""timestamp"": ""2025-06-09T10:00:00Z""}",
- @"{""id"": 1, ""status"": ""processing"", ""timestamp"": ""2025-06-09T10:00:10Z""}",
- @"{""id"": 1, ""status"": ""completed"", ""timestamp"": ""2025-06-09T10:00:20Z""}"
+ @"{""message"": ""Success"", ""data"": {""id"": 1, ""status"": ""pending"", ""timestamp"": ""2025-06-09T10:00:00Z""}}",
+ @"{""message"": ""Success"", ""data"": {""id"": 1, ""status"": ""processing"", ""timestamp"": ""2025-06-09T10:00:10Z""}}",
+ @"{""message"": ""Success"", ""data"": {""id"": 1, ""status"": ""completed"", ""timestamp"": ""2025-06-09T10:00:20Z""}}"
};
// Mock 응답 설정
@@ -780,7 +780,7 @@ namespace UVC.Tests.Data
int repeatInterval = 100;
// Mock 응답 설정
- string mockResponse = @"{""id"": 2, ""status"": ""running"", ""timestamp"": ""2025-06-09T11:00:00Z""}";
+ string mockResponse = @"{""message"": ""Success"", ""data"": {""id"": 2, ""status"": ""running"", ""timestamp"": ""2025-06-09T11:00:00Z""}}";
MockHttpRequester.SetResponse(testUrl, mockResponse);
// DataMask와 DataMapper 설정
@@ -846,8 +846,8 @@ namespace UVC.Tests.Data
int repeatInterval2 = 150;
// Mock 응답 설정
- string mockResponse1 = @"{""id"": 3, ""name"": ""작업1""}";
- string mockResponse2 = @"{""id"": 4, ""name"": ""작업2""}";
+ string mockResponse1 = @"{""message"": ""Success"", ""data"": {""id"": 3, ""name"": ""작업1""}}";
+ string mockResponse2 = @"{""message"": ""Success"", ""data"": {""id"": 4, ""name"": ""작업2""}}";
MockHttpRequester.SetResponse(testUrl1, mockResponse1);
MockHttpRequester.SetResponse(testUrl2, mockResponse2);
@@ -931,7 +931,7 @@ namespace UVC.Tests.Data
int repeatInterval = 100;
// Mock 응답 설정
- string mockResponse = @"{""id"": 5, ""message"": ""자동 중단 테스트""}";
+ string mockResponse = @"{""message"": ""Success"", ""data"": {""id"": 5, ""message"": ""자동 중단 테스트""}}";
MockHttpRequester.SetResponse(testUrl, mockResponse);
// DataMask 설정
diff --git a/Assets/Scripts/UVC/Tests/Data/MQTTPipeLineTests.cs b/Assets/Scripts/UVC/Tests/Data/MQTTPipeLineTests.cs
index cc435688..4d8d3c87 100644
--- a/Assets/Scripts/UVC/Tests/Data/MQTTPipeLineTests.cs
+++ b/Assets/Scripts/UVC/Tests/Data/MQTTPipeLineTests.cs
@@ -43,14 +43,15 @@ namespace UVC.Tests.Data
{
Setup();
Debug.Log("===== MQTTPipeLine 테스트 시작 =====");
+ // 하나씩 테스트 해야 함
//await RunTestAsync(nameof(ExecutePipeLine_AllTopics_RegistersAndHandlesMessages), ExecutePipeLine_AllTopics_RegistersAndHandlesMessages);
//await RunTestAsync(nameof(RemoveTopic_ShouldStopReceivingMessages), RemoveTopic_ShouldStopReceivingMessages);
//await RunTestAsync(nameof(UpdatedDataOnly_ShouldOnlyCallHandlerForUpdatedData), UpdatedDataOnly_ShouldOnlyCallHandlerForUpdatedData);
- await RunTestAsync(nameof(UpdatedDataOnly_WithMockMQTTService_ShouldOnlyReceiveUpdatedData), UpdatedDataOnly_WithMockMQTTService_ShouldOnlyReceiveUpdatedData);
+ //await RunTestAsync(nameof(UpdatedDataOnly_WithMockMQTTService_ShouldOnlyReceiveUpdatedData), UpdatedDataOnly_WithMockMQTTService_ShouldOnlyReceiveUpdatedData);
//RunTest(nameof(OnTopicMessage_ValidJsonObject_CallsHandler), OnTopicMessage_ValidJsonObject_CallsHandler);
//RunTest(nameof(OnTopicMessage_JsonArray_CallsHandler), OnTopicMessage_JsonArray_CallsHandler);
//RunTest(nameof(OnTopicMessage_EmptyMessage_DoesNotCallHandler), OnTopicMessage_EmptyMessage_DoesNotCallHandler);
- //RunTest(nameof(OnTopicMessage_InvalidJson_DoesNotCallHandler), OnTopicMessage_InvalidJson_DoesNotCallHandler);
+ RunTest(nameof(OnTopicMessage_InvalidJson_DoesNotCallHandler), OnTopicMessage_InvalidJson_DoesNotCallHandler);
Debug.Log("===== MQTTPipeLine 테스트 완료 =====");
}
diff --git a/Assets/Scripts/UVC/Tests/MockHttpRequester.cs b/Assets/Scripts/UVC/Tests/MockHttpRequester.cs
index 6d779724..76ce1d93 100644
--- a/Assets/Scripts/UVC/Tests/MockHttpRequester.cs
+++ b/Assets/Scripts/UVC/Tests/MockHttpRequester.cs
@@ -80,7 +80,7 @@ namespace UVC.Tests
}
else
{
- response = GetResponse(url);
+ response = "{\"message\":\"Success\", \"data\":" + GetResponse(url) + "}";
}
if (typeof(T) == typeof(string))
diff --git a/Assets/Scripts/UVC/Tests/Tester.cs b/Assets/Scripts/UVC/Tests/Tester.cs
index ae8fe5e1..5a6f3fa2 100644
--- a/Assets/Scripts/UVC/Tests/Tester.cs
+++ b/Assets/Scripts/UVC/Tests/Tester.cs
@@ -7,8 +7,8 @@ namespace UVC.Tests
public static void RunAllTests()
{
//new DataMapperTests().TestAll();
- //new HttpPipeLineTests().TestAll();
- new MQTTPipeLineTests().TestAll();
+ new HttpPipeLineTests().TestAll();
+ //new MQTTPipeLineTests().TestAll();
}
}
}