diff --git a/XRServer/BaseInfoHandler.cs b/XRServer/HttpHandler.cs
similarity index 74%
rename from XRServer/BaseInfoHandler.cs
rename to XRServer/HttpHandler.cs
index d3bf3e8..6f6f30c 100644
--- a/XRServer/BaseInfoHandler.cs
+++ b/XRServer/HttpHandler.cs
@@ -19,7 +19,7 @@ namespace XRServer
/// 1. 전체 데이터 요청: /baseinfo/01:23 (01분 23초에 해당하는 전체 baseinfo 데이터를 요청)
/// 2. 특정 속성 요청: /Position/01:23 (01분 23초 데이터에서 'Position' 속성만 요청)
///
- public class BaseInfoHandler : IHttpRequestHandler
+ public class HttpHandler : IHttpRequestHandler
{
private SQLiteService _sqliteService;
// 정규식은 매번 컴파일하지 않고, static readonly으로 만들어 한 번만 컴파일하여 재사용하는 것이 성능에 유리합니다.
@@ -28,14 +28,19 @@ namespace XRServer
///
/// 지정된 콘텐츠의 모든 TIMESTAMP 발생을 현재 시간 UTC TIMESTAMP로 바꿀지 여부
///
- public bool ApplyNowTimeStamp { get; set; } = false; // 현재 시간 스탬프를 적용하지 않습니다.
+ public bool ApplyNowTimeStamp { get; set; } = false;
+
+ ///
+ /// Playback 파일이 저장된 폴더의 경로를 가져오거나 설정합니다.
+ ///
+ public string PlaybackFolderPath { get; set; } = string.Empty;
///
/// BaseInfoHandler의 생성자입니다.
///
/// 데이터베이스 작업을 처리하기 위해 외부에서 주입된 SQLiteService 인스턴스입니다. (의존성 주입)
- public BaseInfoHandler(SQLiteService sqliteService)
+ public HttpHandler(SQLiteService sqliteService)
{
this._sqliteService = sqliteService;
}
@@ -49,7 +54,14 @@ namespace XRServer
{
// /baseinfo/분:초(mm:ss format) 문자열을 받아 해당 시간에 대한 SelectBySecondBaseInfo 데이터 반환
string url = context.Request.Uri.OriginalString;
- Logger.Debug($"BaseInfoHandler: {url} 요청 처리 중...");
+ Logger.Debug($"HttpHandler: {url} 요청 처리 중...");
+
+ //url이 '/playback/list'로 시작하는 경우, 다음 핸들러로 넘깁니다.
+ if (url.StartsWith("/playback/list", StringComparison.OrdinalIgnoreCase))
+ {
+ handlePlaybackList(context);
+ return; // '/playback/list' 요청은 별도로 처리하므로 여기서 종료합니다.
+ }
// 1. URL에서 'mm:ss' 형식의 시간 부분이 있는지 정규식으로 확인합니다.
Match match = TimeFormatRegex.Match(url);
@@ -113,6 +125,57 @@ namespace XRServer
}
+ private void handlePlaybackList(IHttpContext context)
+ {
+
+ if(Directory.Exists(PlaybackFolderPath) == false)
+ {
+ // 재생 목록 폴더가 존재하지 않으면 404 오류를 반환합니다.
+ context.Response = new HttpResponse(HttpResponseCode.NotFound, "Playback 폴더가 존재하지 않습니다.", false);
+ return;
+ }
+
+ // 아래 같은 형식의 JSON 객체를 반환합니다.
+ //{
+ // "2024-12-05": {
+ // "0": "2024-12-05_0.sqlite.7z",
+ // "1": "2024-12-05_1.sqlite.7z",
+ // "2": "2024-12-05_2.sqlite.7z",
+ // }
+ //}
+
+ var playbackList = new JObject();
+ // PlaybackFolderPath에서 모든 파일을 검색합니다.
+ var files = Directory.GetFiles(PlaybackFolderPath, "*.sqlite.7z");
+ foreach (var file in files)
+ {
+ // 파일 이름에서 날짜와 인덱스를 추출합니다. 예: "2024-12-05_0.sqlite.7z"
+ string fileName = Path.GetFileNameWithoutExtension(file); // "2024-12-05_0.sqlite"
+ string[] parts = fileName.Split('_'); // ["2024-12-05", "0"]
+ if (parts.Length < 2) continue; // 형식이 잘못된 경우 건너뜁니다.
+ string date = parts[0]; // "2024-12-05"
+ string index = parts[1]; // "0"
+ // 날짜가 없으면 새로 추가하고, 있으면 기존에 추가합니다.
+ if (!playbackList.ContainsKey(date))
+ {
+ playbackList[date] = new JObject();
+ }
+ ((JObject)playbackList[date])[index] = Path.GetFileName(file); // 파일 이름을 추가
+ }
+
+ JObject responsePayload = new JObject();
+ responsePayload["code"] = 20; // 성공 코드
+ responsePayload["message"] = "success"; // 성공 메시지
+ responsePayload["data"] = playbackList; // 재생 목록 데이터
+
+ var headers = new List>
+ {
+ new KeyValuePair("Content-Type", "application/json; charset=utf-8"),
+ };
+
+ context.Response = new HttpResponse(HttpResponseCode.Ok, responsePayload.ToString(Formatting.None), headers, context.Request.Headers.KeepAliveConnection());
+ }
+
///
/// URL 경로에서 요청 타입을 추출합니다. (예: "baseinfo")
///
diff --git a/XRServer/MainWindow.xaml b/XRServer/MainWindow.xaml
index cfe6a0b..826b486 100644
--- a/XRServer/MainWindow.xaml
+++ b/XRServer/MainWindow.xaml
@@ -8,22 +8,24 @@
Title="XR Server" Height="450" Width="840" Closing="Window_Closing" Loaded="Window_Loaded">
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
@@ -56,6 +58,6 @@
-
+
diff --git a/XRServer/MainWindow.xaml.cs b/XRServer/MainWindow.xaml.cs
index d3a174f..e14c3c5 100644
--- a/XRServer/MainWindow.xaml.cs
+++ b/XRServer/MainWindow.xaml.cs
@@ -32,8 +32,9 @@ namespace XRServer
private int mqttPort = 1883; // MQTT 서버 포트
private string sqliteDbPath = string.Empty; // SQLite 데이터베이스 경로
+ private string playbackFolderPath = string.Empty; // playback 폴더 경로
- private BaseInfoHandler httpHandler;
+ private HttpHandler httpHandler;
public MainWindow()
{
@@ -73,11 +74,10 @@ namespace XRServer
// INI 파일에서 설정 값 읽기
sqliteDbPath = ini.GetString("CONFIG", "DB_PATH").Trim();
dbPathTxt.Text = sqliteDbPath;
+ playbackFolderPath = ini.GetString("CONFIG", "PLAYBACK_PATH").Trim();
+ playbackPathTxt.Text = playbackFolderPath;
- if (dbPathTxt.Text == string.Empty || !File.Exists(dbPathTxt.Text))
- {
- startBtn.IsEnabled = false;
- }
+ startBtn.IsEnabled = sqliteDbPath != string.Empty && playbackFolderPath != string.Empty && File.Exists(sqliteDbPath) && Directory.Exists(playbackFolderPath);
}
@@ -97,6 +97,13 @@ namespace XRServer
return;
}
+ if (playbackFolderPath == string.Empty || !Directory.Exists(playbackFolderPath))
+ {
+ Logger.Debug("Playback 폴더 경로가 설정되지 않았습니다. Playback 폴더 경로를 확인하세요.");
+ MessageBox.Show("Playback 폴더 경로가 설정되지 않았습니다. Playback 폴더 경로를 확인하세요.", "오류", MessageBoxButton.OK, MessageBoxImage.Error);
+ return;
+ }
+
if (!sqliteService.Connected)
{
sqliteService.Connect(sqliteDbPath);
@@ -110,6 +117,7 @@ namespace XRServer
mqttPort = int.Parse(mqttPortTxt.Text);
Logger.Debug($"Start Server httpPort:{httpPort} mqttPort:{mqttPort}");
httpHandler.ApplyNowTimeStamp = checkboxTimestamp.IsChecked ?? false;
+ httpHandler.PlaybackFolderPath = playbackFolderPath;
httpServer.Start();
// MQTT 서버 시작
@@ -161,7 +169,7 @@ namespace XRServer
private void InitHttpServer()
{
- httpHandler = new BaseInfoHandler(sqliteService);
+ httpHandler = new HttpHandler(sqliteService);
httpServer.Use(new TcpListenerAdapter(new TcpListener(IPAddress.Loopback, httpPort)));
httpServer.Use(httpHandler);
}
@@ -184,7 +192,7 @@ namespace XRServer
sqliteDbPath = dialog.FileName.Trim();
dbPathTxt.Text = sqliteDbPath;
ini.SetString("CONFIG", "DB_PATH", sqliteDbPath);
- startBtn.IsEnabled = dbPathTxt.Text != string.Empty && File.Exists(dbPathTxt.Text);
+ startBtn.IsEnabled = sqliteDbPath != string.Empty && playbackFolderPath != string.Empty && File.Exists(sqliteDbPath) && Directory.Exists(playbackFolderPath);
}
}
@@ -265,12 +273,24 @@ namespace XRServer
using (StringReader stringReader = new StringReader(data[0].data))
using (JsonTextReader reader = new JsonTextReader(stringReader))
{
+
+ httpPara.Inlines.Add(new LineBreak());
+ string linkString = $"http://localhost:{httpPort}/playback/list";
+ Hyperlink hyperLink = new Hyperlink()
+ {
+ NavigateUri = new Uri(linkString)
+ };
+ hyperLink.Inlines.Add(linkString);
+ hyperLink.RequestNavigate += httpLink_RequestNavigate;
+ httpPara.Inlines.Add(hyperLink);
+
+
JObject jsonObject = JObject.Load(reader);
foreach (var property in jsonObject.Properties())
{
httpPara.Inlines.Add(new LineBreak());
- string linkString = $"http://localhost:{httpPort}/{property.Name}/00:00";
- Hyperlink hyperLink = new Hyperlink()
+ linkString = $"http://localhost:{httpPort}/{property.Name}/00:00";
+ hyperLink = new Hyperlink()
{
NavigateUri = new Uri(linkString)
};
@@ -337,5 +357,25 @@ namespace XRServer
}
}
}
+
+ private void playbackFolderBtn_Click(object sender, RoutedEventArgs e)
+ {
+ // SQLite 데이터베이스 파일 선택 대화상자 열기
+ var dialog = new Microsoft.Win32.OpenFolderDialog();
+
+ // Show open file dialog box
+ bool? result = dialog.ShowDialog();
+
+ // Process open file dialog box results
+ if (result == true)
+ {
+ // Open document
+ playbackFolderPath = dialog.FolderName;
+ playbackPathTxt.Text = playbackFolderPath;
+ ini.SetString("CONFIG", "PLAYBACK_PATH", playbackFolderPath);
+
+ startBtn.IsEnabled = sqliteDbPath != string.Empty && playbackFolderPath != string.Empty && File.Exists(sqliteDbPath) && Directory.Exists(playbackFolderPath);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/XRServer/XRServer.ini b/XRServer/XRServer.ini
index 1d2a722..200b03a 100644
--- a/XRServer/XRServer.ini
+++ b/XRServer/XRServer.ini
@@ -1,2 +1,3 @@
[CONFIG]
-DB_PATH=
\ No newline at end of file
+DB_PATH=
+PLAYBACK_PATH=
\ No newline at end of file
diff --git a/readme.md b/readme.md
index 3ca09d2..ea2dbd4 100644
--- a/readme.md
+++ b/readme.md
@@ -1 +1,2 @@
-XRServer Test 용 Unity 소스
\ No newline at end of file
+XRServer 개발용 서버
+