TIMESTAMP에 현재시간 적용 기능 추가
This commit is contained in:
@@ -25,6 +25,12 @@ namespace XRServer
|
|||||||
// 정규식은 매번 컴파일하지 않고, static readonly으로 만들어 한 번만 컴파일하여 재사용하는 것이 성능에 유리합니다.
|
// 정규식은 매번 컴파일하지 않고, static readonly으로 만들어 한 번만 컴파일하여 재사용하는 것이 성능에 유리합니다.
|
||||||
private static readonly Regex TimeFormatRegex = new Regex(@"([0-5][0-9]):([0-5][0-9])$", RegexOptions.Compiled);
|
private static readonly Regex TimeFormatRegex = new Regex(@"([0-5][0-9]):([0-5][0-9])$", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 지정된 콘텐츠의 모든 TIMESTAMP 발생을 현재 시간 UTC TIMESTAMP로 바꿀지 여부
|
||||||
|
/// </summary>
|
||||||
|
public bool ApplyNowTimeStamp { get; set; } = false; // 현재 시간 스탬프를 적용하지 않습니다.
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// BaseInfoHandler의 생성자입니다.
|
/// BaseInfoHandler의 생성자입니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -70,7 +76,8 @@ namespace XRServer
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 4. 데이터베이스에서 가져온 JSON 문자열을 JObject로 파싱(변환)합니다.
|
// 4. 데이터베이스에서 가져온 JSON 문자열을 JObject로 파싱(변환)합니다.
|
||||||
var jsonData = JObject.Parse(data[0].data);
|
string jsonString = !ApplyNowTimeStamp ? data[0].data : DateTimeUtil.ChangedTimeStampToNow(data[0].data);
|
||||||
|
var jsonData = JObject.Parse(jsonString);
|
||||||
object responseData = null; // 최종적으로 클라이언트에게 보낼 데이터
|
object responseData = null; // 최종적으로 클라이언트에게 보낼 데이터
|
||||||
|
|
||||||
// 5. 요청 타입에 따라 반환할 데이터를 결정합니다.
|
// 5. 요청 타입에 따라 반환할 데이터를 결정합니다.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace XRServer
|
namespace XRServer
|
||||||
@@ -135,5 +136,26 @@ namespace XRServer
|
|||||||
{
|
{
|
||||||
return DateTime.ParseExact(dateTimeString, formatString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
|
return DateTime.ParseExact(dateTimeString, formatString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 지정된 콘텐츠의 모든 TIMESTAMP 발생을 현재 시간 UTC TIMESTAMP로 바꿉니다.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>이 메서드는 "TIMESTAMP":"yyyy-MM-ddTHH:mm:ss", "yyyy-MM-ddTHH:mm:ss.fffZ" 형식의 타임스탬프를 검색하여
|
||||||
|
/// 동일한 형식의 현재 UTC 시간으로 바꿉니다.</remarks>
|
||||||
|
/// <param name="content">업데이트할 타임스탬프가 포함된 문자열 콘텐츠입니다.</param>
|
||||||
|
/// <param name="isUTC">현재 시간을 UTC로 사용할지 여부를 나타내는 부울 값입니다. 기본값은 false입니다.</param>
|
||||||
|
/// <returns>모든 타임스탬프가 현재 UTC 타임스탬프로 바뀐 새 문자열입니다.</returns>
|
||||||
|
public static string ChangedTimeStampToNow(string content, bool isUTC = false)
|
||||||
|
{
|
||||||
|
DateTime now = isUTC ? DateTime.UtcNow : DateTime.Now;
|
||||||
|
// yyyy-MM-ddTHH:mm:ss.fffZ 형식 처리
|
||||||
|
content = Regex.Replace(content, @"TIMESTAMP"":""\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z""", $"TIMESTAMP\":\"{now:yyyy-MM-ddTHH:mm:ss.fffZ}\"");
|
||||||
|
|
||||||
|
// yyyy-MM-ddTHH:mm:ss 형식 처리
|
||||||
|
content = Regex.Replace(content, @"TIMESTAMP"":""\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}""", $"TIMESTAMP\":\"{now:yyyy-MM-ddTHH:mm:ss}\"");
|
||||||
|
|
||||||
|
return content;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Newtonsoft.Json;
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using utils;
|
using utils;
|
||||||
|
|
||||||
@@ -36,6 +37,8 @@ namespace XRServer
|
|||||||
private TimeSpan _currentPlaybackTime = TimeSpan.Zero;
|
private TimeSpan _currentPlaybackTime = TimeSpan.Zero;
|
||||||
private CancellationTokenSource _timerCts;
|
private CancellationTokenSource _timerCts;
|
||||||
private Task _timerTask;
|
private Task _timerTask;
|
||||||
|
// TIMESTAMP(yyyy-MM-ddTHH:mm:ss 2025-03-25T13:00:51)에 현재 시간을 적용 할것인지 여부
|
||||||
|
private bool applyNow = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 매 타임틱마다 호출할 작업을 가져오거나 설정합니다.
|
/// 매 타임틱마다 호출할 작업을 가져오거나 설정합니다.
|
||||||
@@ -200,10 +203,12 @@ namespace XRServer
|
|||||||
|
|
||||||
if (data != null && data.Count > 0)
|
if (data != null && data.Count > 0)
|
||||||
{
|
{
|
||||||
|
string messageData = !applyNow ? data[0].data : DateTimeUtil.ChangedTimeStampToNow(data[0].data);
|
||||||
|
|
||||||
// 전체 토픽 메시지
|
// 전체 토픽 메시지
|
||||||
var messageAll = new MqttApplicationMessageBuilder()
|
var messageAll = new MqttApplicationMessageBuilder()
|
||||||
.WithTopic(topic)
|
.WithTopic(topic)
|
||||||
.WithPayload(data[0].data)
|
.WithPayload(messageData)
|
||||||
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
|
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
|
||||||
.WithRetainFlag(false)
|
.WithRetainFlag(false)
|
||||||
.Build();
|
.Build();
|
||||||
@@ -213,7 +218,7 @@ namespace XRServer
|
|||||||
|
|
||||||
// 개별 프로퍼티 메시지
|
// 개별 프로퍼티 메시지
|
||||||
// json 변환
|
// json 변환
|
||||||
JObject? jsonObject = JsonConvert.DeserializeObject<JObject>(data[0].data);
|
JObject? jsonObject = JsonConvert.DeserializeObject<JObject>(messageData);
|
||||||
if (jsonObject != null)
|
if (jsonObject != null)
|
||||||
{
|
{
|
||||||
string topicString = "";
|
string topicString = "";
|
||||||
@@ -262,8 +267,9 @@ namespace XRServer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Start(string? startTime = null)
|
public async Task Start(string? startTime = null, bool applyNow = false)
|
||||||
{
|
{
|
||||||
|
this.applyNow = applyNow;
|
||||||
if (mqttServer != null)
|
if (mqttServer != null)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(startTime)) SetStartTime(startTime);
|
if (!string.IsNullOrEmpty(startTime)) SetStartTime(startTime);
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="clr-namespace:XRServer"
|
xmlns:local="clr-namespace:XRServer"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="XR Server" Height="400" Width="840" Closing="Window_Closing" Loaded="Window_Loaded">
|
Title="XR Server" Height="450" Width="840" Closing="Window_Closing" Loaded="Window_Loaded">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Button x:Name="startBtn" Content="Start" HorizontalAlignment="Left" Margin="20,268,0,0" VerticalAlignment="Top" Width="247" Height="35" Click="startBtn_Click"/>
|
<Button x:Name="startBtn" Content="Start" HorizontalAlignment="Left" Margin="20,318,0,0" VerticalAlignment="Top" Width="247" Height="35" Click="startBtn_Click"/>
|
||||||
<Button x:Name="startTimeBtn" Content="MQTT 시간 변경" HorizontalAlignment="Left" Margin="147,225,0,0" VerticalAlignment="Top" Width="120" Height="25" Click="startTimeBtn_Click"/>
|
<Button x:Name="startTimeBtn" Content="MQTT 시간 변경" HorizontalAlignment="Left" Margin="147,225,0,0" VerticalAlignment="Top" Width="120" Height="25" Click="startTimeBtn_Click"/>
|
||||||
<Label Content="HTTP Port" HorizontalAlignment="Left" Margin="20,74,0,0" VerticalAlignment="Top"/>
|
<Label Content="HTTP Port" HorizontalAlignment="Left" Margin="20,74,0,0" VerticalAlignment="Top"/>
|
||||||
<TextBox x:Name="httpPortTxt" HorizontalAlignment="Left" Margin="147,80,0,0" TextWrapping="Wrap" Text="8888" VerticalAlignment="Top" Width="120" Height="20" TextChanged="httpPortTxt_TextChanged"/>
|
<TextBox x:Name="httpPortTxt" HorizontalAlignment="Left" Margin="147,80,0,0" TextWrapping="Wrap" Text="8888" VerticalAlignment="Top" Width="120" Height="20" TextChanged="httpPortTxt_TextChanged"/>
|
||||||
@@ -23,7 +23,8 @@
|
|||||||
<Label Content="DB File" HorizontalAlignment="Left" Margin="20,20,0,0" VerticalAlignment="Top"/>
|
<Label Content="DB File" HorizontalAlignment="Left" Margin="20,20,0,0" VerticalAlignment="Top"/>
|
||||||
<TextBox x:Name="dbPathTxt" HorizontalAlignment="Left" Margin="20,43,0,0" VerticalAlignment="Top" TextWrapping="Wrap" Text="" Width="180" Height="20" IsReadOnly="True"/>
|
<TextBox x:Name="dbPathTxt" HorizontalAlignment="Left" Margin="20,43,0,0" VerticalAlignment="Top" TextWrapping="Wrap" Text="" Width="180" Height="20" IsReadOnly="True"/>
|
||||||
<Button x:Name="dbFileLoadBtn" Content="설정" HorizontalAlignment="Left" Margin="212,43,0,0" VerticalAlignment="Top" Width="55" Height="20" Click="dbFileLoadBtn_Click"/>
|
<Button x:Name="dbFileLoadBtn" Content="설정" HorizontalAlignment="Left" Margin="212,43,0,0" VerticalAlignment="Top" Width="55" Height="20" Click="dbFileLoadBtn_Click"/>
|
||||||
<ScrollViewer HorizontalAlignment="Left" Margin="300,43,0,0" VerticalAlignment="Top" Width="250" Height="260">
|
<CheckBox x:Name="checkboxTimestamp" Content="TIMESTAMP에 현재 시간 적용" HorizontalAlignment="Left" Margin="22,271,0,0" VerticalAlignment="Top"/>
|
||||||
|
<ScrollViewer HorizontalAlignment="Left" Margin="300,43,0,0" VerticalAlignment="Top" Width="250" Height="310">
|
||||||
<RichTextBox x:Name="httpLinkTxtBlock" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto"
|
<RichTextBox x:Name="httpLinkTxtBlock" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||||
IsReadOnly="True" IsDocumentEnabled="True">
|
IsReadOnly="True" IsDocumentEnabled="True">
|
||||||
<FlowDocument>
|
<FlowDocument>
|
||||||
@@ -39,7 +40,7 @@
|
|||||||
</FlowDocument>
|
</FlowDocument>
|
||||||
</RichTextBox>
|
</RichTextBox>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
<ScrollViewer HorizontalAlignment="Left" Margin="560,43,0,0" VerticalAlignment="Top" Width="250" Height="260">
|
<ScrollViewer HorizontalAlignment="Left" Margin="560,43,0,0" VerticalAlignment="Top" Width="250" Height="310">
|
||||||
<RichTextBox x:Name="mqttLinkTxtBlock" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto"
|
<RichTextBox x:Name="mqttLinkTxtBlock" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||||
IsReadOnly="True" IsDocumentEnabled="True">
|
IsReadOnly="True" IsDocumentEnabled="True">
|
||||||
<FlowDocument>
|
<FlowDocument>
|
||||||
@@ -55,5 +56,6 @@
|
|||||||
</FlowDocument>
|
</FlowDocument>
|
||||||
</RichTextBox>
|
</RichTextBox>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ namespace XRServer
|
|||||||
|
|
||||||
private string sqliteDbPath = string.Empty; // SQLite 데이터베이스 경로
|
private string sqliteDbPath = string.Empty; // SQLite 데이터베이스 경로
|
||||||
|
|
||||||
|
private BaseInfoHandler httpHandler;
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -107,11 +109,12 @@ namespace XRServer
|
|||||||
httpPort = int.Parse(httpPortTxt.Text);
|
httpPort = int.Parse(httpPortTxt.Text);
|
||||||
mqttPort = int.Parse(mqttPortTxt.Text);
|
mqttPort = int.Parse(mqttPortTxt.Text);
|
||||||
Logger.Debug($"Start Server httpPort:{httpPort} mqttPort:{mqttPort}");
|
Logger.Debug($"Start Server httpPort:{httpPort} mqttPort:{mqttPort}");
|
||||||
|
httpHandler.ApplyNowTimeStamp = checkboxTimestamp.IsChecked ?? false;
|
||||||
httpServer.Start();
|
httpServer.Start();
|
||||||
|
|
||||||
// MQTT 서버 시작
|
// MQTT 서버 시작
|
||||||
mqttService.SetConfig(mqttPort, mqttTopicTxt.Text, mqttTopicTxt2.Text);
|
mqttService.SetConfig(mqttPort, mqttTopicTxt.Text, mqttTopicTxt2.Text);
|
||||||
await mqttService.Start(mqttStartTimeTxt.Text);
|
await mqttService.Start(mqttStartTimeTxt.Text, checkboxTimestamp.IsChecked ?? false);
|
||||||
|
|
||||||
startBtn.Content = "Stop";
|
startBtn.Content = "Stop";
|
||||||
httpPortTxt.IsEnabled = false;
|
httpPortTxt.IsEnabled = false;
|
||||||
@@ -120,6 +123,7 @@ namespace XRServer
|
|||||||
mqttLink.IsEnabled = true;
|
mqttLink.IsEnabled = true;
|
||||||
mqttTopicTxt.IsEnabled = false;
|
mqttTopicTxt.IsEnabled = false;
|
||||||
mqttTopicTxt2.IsEnabled = false;
|
mqttTopicTxt2.IsEnabled = false;
|
||||||
|
checkboxTimestamp.IsEnabled = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -136,6 +140,7 @@ namespace XRServer
|
|||||||
mqttLink.IsEnabled = false;
|
mqttLink.IsEnabled = false;
|
||||||
mqttTopicTxt.IsEnabled = true;
|
mqttTopicTxt.IsEnabled = true;
|
||||||
mqttTopicTxt2.IsEnabled = true;
|
mqttTopicTxt2.IsEnabled = true;
|
||||||
|
checkboxTimestamp.IsEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
isRunning = !isRunning;
|
isRunning = !isRunning;
|
||||||
@@ -156,8 +161,9 @@ namespace XRServer
|
|||||||
|
|
||||||
private void InitHttpServer()
|
private void InitHttpServer()
|
||||||
{
|
{
|
||||||
|
httpHandler = new BaseInfoHandler(sqliteService);
|
||||||
httpServer.Use(new TcpListenerAdapter(new TcpListener(IPAddress.Loopback, httpPort)));
|
httpServer.Use(new TcpListenerAdapter(new TcpListener(IPAddress.Loopback, httpPort)));
|
||||||
httpServer.Use(new BaseInfoHandler(sqliteService));
|
httpServer.Use(httpHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dbFileLoadBtn_Click(object sender, RoutedEventArgs e)
|
private void dbFileLoadBtn_Click(object sender, RoutedEventArgs e)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
<Platforms>AnyCPU;x86</Platforms>
|
<Platforms>AnyCPU;x86</Platforms>
|
||||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||||
|
<Version>1.0.1</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user