diff --git a/SmartAquaViewer/Controls/FFPlayerControl.xaml b/SmartAquaViewer/Controls/FFPlayerControl.xaml
index ea2f968..c82e901 100644
--- a/SmartAquaViewer/Controls/FFPlayerControl.xaml
+++ b/SmartAquaViewer/Controls/FFPlayerControl.xaml
@@ -6,13 +6,13 @@
xmlns:local="clr-namespace:SmartAquaViewer.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
-
+
-
+
diff --git a/SmartAquaViewer/MainWindow.xaml b/SmartAquaViewer/MainWindow.xaml
index 69256c3..a2ee1f9 100644
--- a/SmartAquaViewer/MainWindow.xaml
+++ b/SmartAquaViewer/MainWindow.xaml
@@ -93,9 +93,8 @@
CommandParameter="{Binding Tag, RelativeSource={RelativeSource Self}}"/>
-
-
-
+
+
diff --git a/SmartAquaViewer/Model/CCTVInfo.cs b/SmartAquaViewer/Model/CCTVInfo.cs
index 11fd0ef..4eaf1c0 100644
--- a/SmartAquaViewer/Model/CCTVInfo.cs
+++ b/SmartAquaViewer/Model/CCTVInfo.cs
@@ -1,16 +1,35 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Linq;
+using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace SmartAquaViewer.Model
{
- public class CCTVInfo
+ public class CCTVInfo : INotifyPropertyChanged
{
public string? DeviceId { get; set; }
public string? DeviceName { get; set; }
public string? RtspUrl { get; set; }
- public string? Status { get; set; }
+
+ private CCTVStatus? _status;
+ public CCTVStatus? Status
+ {
+ get => _status;
+ set
+ {
+ if (_status != value)
+ {
+ _status = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ public event PropertyChangedEventHandler? PropertyChanged;
+ private void OnPropertyChanged([CallerMemberName] string? name = null)
+ => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
diff --git a/SmartAquaViewer/Model/Enums.cs b/SmartAquaViewer/Model/Enums.cs
index 4f6b500..377c66f 100644
--- a/SmartAquaViewer/Model/Enums.cs
+++ b/SmartAquaViewer/Model/Enums.cs
@@ -25,6 +25,7 @@ namespace SmartAquaViewer.Model
public enum StepFieldKind
{
+ Time,
Status, // 전원/상태
Sensor, // 센서 값
Energy, // 에너지 소비량
@@ -42,4 +43,10 @@ namespace SmartAquaViewer.Model
Energy,
GreenhouseGas
}
+
+ public enum CCTVStatus
+ {
+ Disconnected,
+ Connected
+ }
}
diff --git a/SmartAquaViewer/Resources/Generic.xaml b/SmartAquaViewer/Resources/Generic.xaml
index 6ecf346..983ddba 100644
--- a/SmartAquaViewer/Resources/Generic.xaml
+++ b/SmartAquaViewer/Resources/Generic.xaml
@@ -177,4 +177,30 @@
+
+
+
+
\ No newline at end of file
diff --git a/SmartAquaViewer/Resources/Images/arrow_left.png b/SmartAquaViewer/Resources/Images/arrow_left.png
new file mode 100644
index 0000000..8922cce
Binary files /dev/null and b/SmartAquaViewer/Resources/Images/arrow_left.png differ
diff --git a/SmartAquaViewer/Resources/Images/arrow_right.png b/SmartAquaViewer/Resources/Images/arrow_right.png
new file mode 100644
index 0000000..e3a81c2
Binary files /dev/null and b/SmartAquaViewer/Resources/Images/arrow_right.png differ
diff --git a/SmartAquaViewer/SmartAquaViewer.csproj b/SmartAquaViewer/SmartAquaViewer.csproj
index 6fbd482..8756b8e 100644
--- a/SmartAquaViewer/SmartAquaViewer.csproj
+++ b/SmartAquaViewer/SmartAquaViewer.csproj
@@ -21,6 +21,8 @@
+
+
@@ -70,6 +72,12 @@
+
+ PreserveNewest
+
+
+ PreserveNewest
+
diff --git a/SmartAquaViewer/View/CCTVView.xaml b/SmartAquaViewer/View/CCTVView.xaml
index d22bc3a..90e9035 100644
--- a/SmartAquaViewer/View/CCTVView.xaml
+++ b/SmartAquaViewer/View/CCTVView.xaml
@@ -6,20 +6,129 @@
xmlns:local="clr-namespace:SmartAquaViewer.View"
xmlns:classes="clr-namespace:SmartAquaViewer.Classes"
xmlns:controls="clr-namespace:SmartAquaViewer.Controls"
+ xmlns:helper="clr-namespace:SmartAquaViewer.Helper"
+ xmlns:model="clr-namespace:SmartAquaViewer.Model"
+ xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SmartAquaViewer/View/EnegyView.xaml b/SmartAquaViewer/View/EnegyView.xaml
index 41456dd..7970bbe 100644
--- a/SmartAquaViewer/View/EnegyView.xaml
+++ b/SmartAquaViewer/View/EnegyView.xaml
@@ -13,356 +13,358 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
diff --git a/SmartAquaViewer/View/FileListView.xaml b/SmartAquaViewer/View/FileListView.xaml
index dfdee66..24867b3 100644
--- a/SmartAquaViewer/View/FileListView.xaml
+++ b/SmartAquaViewer/View/FileListView.xaml
@@ -24,7 +24,7 @@
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
diff --git a/SmartAquaViewer/View/MonitoringView.xaml b/SmartAquaViewer/View/MonitoringView.xaml
index 81c7a63..2dad47b 100644
--- a/SmartAquaViewer/View/MonitoringView.xaml
+++ b/SmartAquaViewer/View/MonitoringView.xaml
@@ -16,8 +16,8 @@
-
-
+
+
diff --git a/SmartAquaViewer/ViewModel/CCTVViewModel.cs b/SmartAquaViewer/ViewModel/CCTVViewModel.cs
index caf58f4..5ee6911 100644
--- a/SmartAquaViewer/ViewModel/CCTVViewModel.cs
+++ b/SmartAquaViewer/ViewModel/CCTVViewModel.cs
@@ -6,6 +6,9 @@ using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Input;
+using SmartAquaViewer.Controls;
using SmartAquaViewer.DataAnalysis;
using SmartAquaViewer.Model;
@@ -13,7 +16,7 @@ namespace SmartAquaViewer.ViewModel
{
public class CCTVViewModel : INotifyPropertyChanged
{
- public List CCTVInfoList { get; } = new List();
+ public ObservableCollection CCTVInfoList { get; } = new ObservableCollection();
public ObservableCollection PlayerVMs { get; } = new();
@@ -45,72 +48,179 @@ namespace SmartAquaViewer.ViewModel
}
}
+ private bool _isOpenMode;
+ public bool IsOpenMode
+ {
+ get => _isOpenMode;
+ set
+ {
+ if (_isOpenMode != value)
+ {
+ _isOpenMode = value;
+ OnPropertyChanged();
+
+ BtnVisibilityLeft = _isOpenMode ? Visibility.Collapsed : Visibility.Visible;
+ BtnVisibilityRight = _isOpenMode ? Visibility.Visible : Visibility.Collapsed;
+ }
+ }
+ }
+
+ private Visibility _btnVisibilityLeft;
+ public Visibility BtnVisibilityLeft
+ {
+ get => _btnVisibilityLeft;
+ set
+ {
+ if (_btnVisibilityLeft != value)
+ {
+ _btnVisibilityLeft = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ private Visibility _btnVisibilityRight;
+ public Visibility BtnVisibilityRight
+ {
+ get => _btnVisibilityRight;
+ set
+ {
+ if (_btnVisibilityRight != value)
+ {
+ _btnVisibilityRight = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ private Visibility _btnVisibilityPlay;
+ public Visibility BtnVisibilityPlay
+ {
+ get => _btnVisibilityPlay;
+ set
+ {
+ if (_btnVisibilityPlay != value)
+ {
+ _btnVisibilityPlay = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ private Visibility _btnVisibilityStop;
+ public Visibility BtnVisibilityStop
+ {
+ get => _btnVisibilityStop;
+ set
+ {
+ if (_btnVisibilityStop != value)
+ {
+ _btnVisibilityStop = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ public ICommand ChangeDrawerStatusCommand { get; }
+
+ public ICommand PlayAllCCTVCommand { get; }
+
+ public ICommand StopAllCCTVCommand { get; }
+
+
+
public CCTVViewModel()
{
ColumnCount = 4; // Default value
RowCount = 2; // Default value
- CCTVInfoList = new List()
+ IsOpenMode = false;
+ BtnVisibilityRight = Visibility.Collapsed;
+ BtnVisibilityStop = Visibility.Collapsed;
+
+ CCTVInfoList = new ObservableCollection()
{
new()
{
DeviceId = "000001",
DeviceName = "CCTV 1",
RtspUrl = "rtsp://210.217.121.58:8554/CAM-211",
- Status = "Active"
+ Status = CCTVStatus.Disconnected
},
new()
{
DeviceId = "000002",
DeviceName = "CCTV 2",
RtspUrl = "rtsp://210.217.121.58:8554/CAM-212",
- Status = "Active"
+ Status = CCTVStatus.Disconnected
},
new()
{
DeviceId = "000003",
DeviceName = "CCTV 3",
RtspUrl = "rtsp://210.217.121.58:8554/CAM-01",
- Status = "Active"
+ Status = CCTVStatus.Disconnected
},
new()
{
DeviceId = "000004",
DeviceName = "CCTV 4",
RtspUrl = "rtsp://210.217.121.58:8554/CAM-02",
- Status = "Active"
+ Status = CCTVStatus.Disconnected
},
new()
{
DeviceId = "000005",
DeviceName = "CCTV 5",
RtspUrl = "rtsp://210.217.121.58:8554/CAM-03",
- Status = "Active"
+ Status = CCTVStatus.Disconnected
},
new()
{
DeviceId = "000006",
DeviceName = "CCTV 6",
RtspUrl = "rtsp://210.217.121.58:8554/CAM-04",
- Status = "Active"
+ Status = CCTVStatus.Disconnected
},
new()
{
DeviceId = "000007",
DeviceName = "CCTV 7",
RtspUrl = "rtsp://210.217.121.58:8554/CAM-05",
- Status = "Active"
+ Status = CCTVStatus.Disconnected
},
new()
{
DeviceId = "000008",
DeviceName = "CCTV 8",
RtspUrl = "rtsp://210.217.121.58:8554/CAM-06",
- Status = "Active"
+ Status = CCTVStatus.Disconnected
}
};
BuildPlayers(CCTVInfoList);
+
+ ChangeDrawerStatusCommand = new RelayCommand(_ => IsOpenMode = !IsOpenMode);
+ PlayAllCCTVCommand = new RelayCommand(PlayAllCCTV);
+ StopAllCCTVCommand = new RelayCommand(StopAllCCTV);
+ }
+
+ private void PlayAllCCTV(object obj)
+ {
+ foreach (var ff in PlayerVMs)
+ ff.StartMedia(ff.CCTVInfo.RtspUrl!);
+
+ BtnVisibilityPlay = Visibility.Collapsed;
+ BtnVisibilityStop = Visibility.Visible;
+ }
+
+ private void StopAllCCTV(object obj)
+ {
+ foreach (var ff in PlayerVMs)
+ ff.ClosePlayer();
+
+ BtnVisibilityPlay = Visibility.Visible;
+ BtnVisibilityStop = Visibility.Collapsed;
}
public void BuildPlayers(IEnumerable infos)
diff --git a/SmartAquaViewer/ViewModel/FFPlayerViewModel.cs b/SmartAquaViewer/ViewModel/FFPlayerViewModel.cs
index 47a7176..8cd660b 100644
--- a/SmartAquaViewer/ViewModel/FFPlayerViewModel.cs
+++ b/SmartAquaViewer/ViewModel/FFPlayerViewModel.cs
@@ -1,14 +1,7 @@
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.ComponentModel;
+using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
-using System.Linq;
using System.Runtime.CompilerServices;
-using System.Security.Policy;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
@@ -30,14 +23,21 @@ namespace SmartAquaViewer.ViewModel
set { _currentFrame = value; OnPropertyChanged(); }
}
+ private Visibility _isPlayingVIsibility;
+ public Visibility IsPlayingVIsibility
+ {
+ get => _isPlayingVIsibility;
+ set { _isPlayingVIsibility = value; OnPropertyChanged(); }
+ }
+
//private readonly System.Windows.Controls.Image _img;
- private readonly object _lockObject = new object();
private Thread _videoThread;
private Thread _renderingThread;
private CancellationTokenSource _videoCts;
private CancellationTokenSource _renderCts;
+ private readonly object _lockObject = new object();
private readonly Queue _frameQueue = new(); // lock 불필요
private volatile bool _disposed;
@@ -48,11 +48,14 @@ namespace SmartAquaViewer.ViewModel
CCTVInfo = cctvInfo;
_ui = Application.Current?.Dispatcher ?? Dispatcher.CurrentDispatcher; // UI 디스패처 보관
- StartMedia(CCTVInfo.RtspUrl!);
+ IsPlayingVIsibility = Visibility.Visible;
}
public void StartMedia(string rtspURL)
{
+ IsPlayingVIsibility = Visibility.Collapsed;
+ CCTVInfo.Status = CCTVStatus.Connected;
+
_videoCts = new CancellationTokenSource();
_renderCts = new CancellationTokenSource();
@@ -178,6 +181,11 @@ namespace SmartAquaViewer.ViewModel
_videoCts?.Dispose();
_renderCts?.Dispose();
+
+ CurrentFrame = null;
+
+ IsPlayingVIsibility = Visibility.Visible;
+ CCTVInfo.Status = CCTVStatus.Disconnected;
}
public event PropertyChangedEventHandler? PropertyChanged;
diff --git a/SmartAquaViewer/ViewModel/GraphControlViewModel.cs b/SmartAquaViewer/ViewModel/GraphControlViewModel.cs
index 59ca9fe..3e16899 100644
--- a/SmartAquaViewer/ViewModel/GraphControlViewModel.cs
+++ b/SmartAquaViewer/ViewModel/GraphControlViewModel.cs
@@ -326,7 +326,7 @@ namespace SmartAquaViewer.ViewModel
.ToList();
// X축 라벨
- xAxis.Labels.AddRange(timeBuckets.Select(t => t.ToString("MM-dd HH:mm")));
+ xAxis.Labels.AddRange(timeBuckets.Select(t => t.ToString("HH:mm:ss")));
var allTankIds = collection.SelectMany(w => w.Tanks).Select(t => t.Number).Distinct().OrderBy(id => id).ToList();
var tankIds = (selectedTankNums == null || !selectedTankNums.Any())
diff --git a/SmartAquaViewer/ViewModel/MainViewModel.cs b/SmartAquaViewer/ViewModel/MainViewModel.cs
index 5f9826b..f8dd18c 100644
--- a/SmartAquaViewer/ViewModel/MainViewModel.cs
+++ b/SmartAquaViewer/ViewModel/MainViewModel.cs
@@ -17,19 +17,7 @@ namespace SmartAquaViewer.ViewModel
{
public class MainViewModel : INotifyPropertyChanged
{
- private string _appTitle;
- public string AppTitle
- {
- get => _appTitle;
- set
- {
- if (_appTitle != value)
- {
- _appTitle = value;
- OnPropertyChanged(nameof(AppTitle));
- }
- }
- }
+ public string AppTitle { get; set; } = string.Empty;
private object? _selectedViewModel;
public object? SelectedViewModel
diff --git a/SmartAquaViewer/ViewModel/MonitoringViewModel.cs b/SmartAquaViewer/ViewModel/MonitoringViewModel.cs
index 690dae7..cb38640 100644
--- a/SmartAquaViewer/ViewModel/MonitoringViewModel.cs
+++ b/SmartAquaViewer/ViewModel/MonitoringViewModel.cs
@@ -1,18 +1,11 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
+using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
-using System.Diagnostics;
-using System.Linq;
using System.Runtime.CompilerServices;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using SmartAquaViewer.Controls;
-using SmartAquaViewer.DataAnalisys;
using SmartAquaViewer.DataAnalysis;
using SmartAquaViewer.Model;
@@ -52,8 +45,6 @@ namespace SmartAquaViewer.ViewModel
public ObservableCollection TanksByTimes { get; } = new();
- private ObservableCollection SelectedTankNumbers { get; } = new();
-
private MonitorTab _selectedTab;
public MonitorTab SelectedTab
{
@@ -355,16 +346,6 @@ namespace SmartAquaViewer.ViewModel
var keys = SelectedWaterTanks.Keys.ToList();
- var selectedTanks = WaterQualityList
- .SelectMany(wq => wq.Tanks.Select(tank => new { Tank = tank, VO = wq }))
- .Where(x => keys.Contains(x.Tank.Number))
- .GroupBy(x => x.Tank.Number)
- .ToDictionary(
- g => g.Key,
- g => new ObservableCollection(
- g.Select(x => x.VO).OrderBy(vo => vo.RecordedTime))
- );
-
GraphControlVM.SetTankLineGraph(WaterQualityList, keys, SelectedXField, SelectedYField, ShowMarkers, ShowLegends);
}
@@ -377,7 +358,7 @@ namespace SmartAquaViewer.ViewModel
var keys = SelectedWaterTanks.Keys.ToList();
- GraphControlVM.SetBoxPlot(WaterQualityList, keys, SelectedXField, SelectedYField, BoxWidth, boxTimeSpan);
+ GraphControlVM.SetBoxPlot(WaterQualityList, keys, SelectedXField!, SelectedYField, BoxWidth, boxTimeSpan);
}
private void SetGraphData_Scatter_Tank()
@@ -387,7 +368,7 @@ namespace SmartAquaViewer.ViewModel
var keys = SelectedWaterTanks.Keys.ToList();
- GraphControlVM.SetScatterPlot(WaterQualityList, SelectedXField, SelectedYField, keys, ScatterMarkerSize, ShowRegression, ShowLegends);
+ GraphControlVM.SetScatterPlot(WaterQualityList, SelectedXField!, SelectedYField, keys, ScatterMarkerSize, ShowRegression, ShowLegends);
}
private void SetGraphType()
@@ -414,7 +395,7 @@ namespace SmartAquaViewer.ViewModel
{
SelectedGraphIndex = -1;
SelectedGraphIndex = GraphTypes.Count > 0 ? 0 : -1;
- }), System.Windows.Threading.DispatcherPriority.Background);
+ }), DispatcherPriority.Background);
}
private void RebuildAvailableFields()
@@ -422,7 +403,7 @@ namespace SmartAquaViewer.ViewModel
AvailableFields.Clear();
// 공통 시간
- AvailableFields.Add(new FieldItem { Name = "RecordedTime", Display = "시간", DataType = typeof(DateTime) });
+ AvailableFields.Add(new FieldItem { Name = "RecordedTime", Display = "시간", DataType = typeof(DateTime), Kind = StepFieldKind.Time });
if (SelectedTab == MonitorTab.Tank)
{
@@ -496,7 +477,10 @@ namespace SmartAquaViewer.ViewModel
if ((SelectedGraphType == GraphType.LINE
|| SelectedGraphType == GraphType.STEP
|| SelectedGraphType == GraphType.SCATTER)
- && f.Name.Equals("Number")) continue;
+ && f.Name!.Equals("Number")) continue;
+ if (SelectedGraphType == GraphType.LINE
+ && (f.Kind.Equals(StepFieldKind.Status)
+ || f.Name!.Equals("Filtering.InverterControllerStatus"))) continue;
XFieldCandidates.Add(f);
if (SelectedGraphType == GraphType.STEP || SelectedGraphType == GraphType.BOX) break;
}