Added some comments

This commit is contained in:
Marvin Lehmann 2019-07-18 20:37:56 +02:00
parent 184e981aac
commit af690f4213
5 changed files with 70 additions and 10 deletions

View File

@ -1,15 +1,15 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
namespace FrontEnd namespace FrontEnd
{ {
/// <summary>
/// Class to represent the JSON cam object returned by the central web service.
/// </summary>
public class Cam public class Cam
{ {
public int Id { get; set; } public int Id { get; set; }
@ -29,6 +29,9 @@ namespace FrontEnd
} }
} }
/// <summary>
/// Class to represent the JSON client object returned by the central web service.
/// </summary>
public class Client public class Client
{ {
public int Id { get; set; } public int Id { get; set; }
@ -46,6 +49,13 @@ namespace FrontEnd
} }
} }
/// <summary>
/// Class to communicate with the central web service:
/// <list type="bullet">
/// <item><description>retrieves and deserializes JSON objects to <seealso cref="Client"/> and <seealso cref="Cam"/> objects,</description></item>
/// <item><description>retrieves images</description></item>
/// </list>
/// </summary>
class Communicator class Communicator
{ {
static private HttpClient client = new HttpClient(); static private HttpClient client = new HttpClient();
@ -92,11 +102,19 @@ namespace FrontEnd
return img; return img;
} }
/// <summary>
/// Returns the url to the processed camera stream.
/// </summary>
public static string GetProcessedCameraAddress(Cam cam) public static string GetProcessedCameraAddress(Cam cam)
{ {
return $"{client.BaseAddress.AbsoluteUri}cam/{cam.Id}/processed"; return $"{client.BaseAddress.AbsoluteUri}cam/{cam.Id}/processed";
} }
/// <summary>
/// Converts a byte array to a bitmap image.
/// </summary>
/// <param name="array">byte array representing an image</param>
/// <returns>converted Image</returns>
public static BitmapImage BytesToImage(byte[] array) public static BitmapImage BytesToImage(byte[] array)
{ {
using (var ms = new System.IO.MemoryStream(array)) using (var ms = new System.IO.MemoryStream(array))

View File

@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FrontEnd" xmlns:local="clr-namespace:FrontEnd"
mc:Ignorable="d" mc:Ignorable="d"
Title="MainWindow" Height="517.5" Width="800" Title="Client" Height="517.5" Width="800"
Loaded="Window_Loaded"> Loaded="Window_Loaded">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>

View File

@ -1,16 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
namespace FrontEnd namespace FrontEnd
@ -23,12 +19,18 @@ namespace FrontEnd
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
// Load and set canvas background image.
var img = new BitmapImage(new Uri(@"pack://application:,,,/Images/map.png")); var img = new BitmapImage(new Uri(@"pack://application:,,,/Images/map.png"));
imgMap.Source = img; imgMap.Source = img;
} }
/// <summary>
/// Creates a camera marker on the map.
/// </summary>
private void CreateCameraMarker(Point pos, Cam cam) private void CreateCameraMarker(Point pos, Cam cam)
{ {
// Represent the client with a custom images.
// Load the green camera image from the resources when it's active and the red one when not.
var img = new Image var img = new Image
{ {
Source = new BitmapImage(new Uri($@"pack://application:,,,/Images/cam_{(cam.Status ? "green" : "red")}.png")), Source = new BitmapImage(new Uri($@"pack://application:,,,/Images/cam_{(cam.Status ? "green" : "red")}.png")),
@ -39,13 +41,20 @@ namespace FrontEnd
Tag = cam, Tag = cam,
ToolTip = cam.Label ToolTip = cam.Label
}; };
// Set mouse event handlers.
img.MouseDown += Cam_MouseDown; img.MouseDown += Cam_MouseDown;
img.MouseEnter += Img_MouseEnter; img.MouseEnter += Img_MouseEnter;
// Place the camera image on the canvas.
cnvMap.Children.Add(img); cnvMap.Children.Add(img);
Canvas.SetLeft(img, pos.X - img.Width / 2); Canvas.SetLeft(img, pos.X - img.Width / 2);
Canvas.SetTop(img, pos.Y - img.Height / 2); Canvas.SetTop(img, pos.Y - img.Height / 2);
} }
/// <summary>
/// Select the corresponding list item of the hovered camera marker.
/// </summary>
private void Img_MouseEnter(object sender, MouseEventArgs e) private void Img_MouseEnter(object sender, MouseEventArgs e)
{ {
var cam = (Cam)((Image)sender).Tag; var cam = (Cam)((Image)sender).Tag;
@ -56,6 +65,9 @@ namespace FrontEnd
lstDevices.SelectedItem = newSelection.First(); lstDevices.SelectedItem = newSelection.First();
} }
/// <summary>
/// Show the stream of the hovered camera marker. (LMB = original stream, LMB = processed stream)
/// </summary>
private void Cam_MouseDown(object sender, MouseButtonEventArgs e) private void Cam_MouseDown(object sender, MouseButtonEventArgs e)
{ {
var cam = (Cam)((Image)sender).Tag; var cam = (Cam)((Image)sender).Tag;
@ -65,8 +77,13 @@ namespace FrontEnd
new StreamWindow(cam, true).ShowDialog(); new StreamWindow(cam, true).ShowDialog();
} }
/// <summary>
/// Creates a client marker on the map.
/// </summary>
private void CreateClientMarker(Point pos, Client client) private void CreateClientMarker(Point pos, Client client)
{ {
// Represent the client with a colored ellipse.
// The color is green when active and red when not.
var ellipse = new Ellipse var ellipse = new Ellipse
{ {
Width = 20, Width = 20,
@ -77,12 +94,19 @@ namespace FrontEnd
ToolTip = client.Label, ToolTip = client.Label,
Tag = client Tag = client
}; };
// Set mouse event handlers.
ellipse.MouseEnter += Ellipse_MouseEnter; ellipse.MouseEnter += Ellipse_MouseEnter;
// Place the ellipse on the canvas.
cnvMap.Children.Add(ellipse); cnvMap.Children.Add(ellipse);
Canvas.SetLeft(ellipse, pos.X - ellipse.Width / 2); Canvas.SetLeft(ellipse, pos.X - ellipse.Width / 2);
Canvas.SetTop(ellipse, pos.Y - ellipse.Height / 2); Canvas.SetTop(ellipse, pos.Y - ellipse.Height / 2);
} }
/// <summary>
/// Select the corresponding list item of the hovered client marker.
/// </summary>
private void Ellipse_MouseEnter(object sender, MouseEventArgs e) private void Ellipse_MouseEnter(object sender, MouseEventArgs e)
{ {
var client = (Client)((Ellipse)sender).Tag; var client = (Client)((Ellipse)sender).Tag;
@ -96,6 +120,8 @@ namespace FrontEnd
private void Window_Loaded(object sender, RoutedEventArgs e) private void Window_Loaded(object sender, RoutedEventArgs e)
{ {
LoadInformation(); LoadInformation();
// Set a timer to periodically reload shown information.
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer(); System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick); dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 5); dispatcherTimer.Interval = new TimeSpan(0, 0, 5);
@ -104,6 +130,7 @@ namespace FrontEnd
private void dispatcherTimer_Tick(object sender, EventArgs e) private void dispatcherTimer_Tick(object sender, EventArgs e)
{ {
// Get the current selected list item to restore the selection after refresh.
var selectedItem = (ListBoxItem)lstDevices.SelectedItem; var selectedItem = (ListBoxItem)lstDevices.SelectedItem;
LoadInformation(); LoadInformation();
if (selectedItem != null) if (selectedItem != null)
@ -116,17 +143,25 @@ namespace FrontEnd
} }
} }
/// <summary>
/// Populates the canvas map and device list.
/// </summary>
private void LoadInformation() private void LoadInformation()
{ {
// Retrieve cam and client objects.
List<Cam> cams = Task.Run(async () => { return await Communicator.GetCamsAsync(); }).Result; List<Cam> cams = Task.Run(async () => { return await Communicator.GetCamsAsync(); }).Result;
List<Client> clients = Task.Run(async () => { return await Communicator.GetClientsAsync(); }).Result; List<Client> clients = Task.Run(async () => { return await Communicator.GetClientsAsync(); }).Result;
// Clear canvas map and properly set it's size.
cnvMap.Children.Clear(); cnvMap.Children.Clear();
cnvMap.Width = imgMap.ActualWidth; cnvMap.Width = imgMap.ActualWidth;
cnvMap.Height = imgMap.ActualHeight; cnvMap.Height = imgMap.ActualHeight;
// Also clear the list and description textbox.
lstDevices.Items.Clear(); lstDevices.Items.Clear();
txtInfo.Clear(); txtInfo.Clear();
// Create client markers on canvas map.
foreach (var client in clients) foreach (var client in clients)
{ {
CreateClientMarker(new Point(cnvMap.Width * client.X, cnvMap.Height * client.Y), client); CreateClientMarker(new Point(cnvMap.Width * client.X, cnvMap.Height * client.Y), client);
@ -134,8 +169,10 @@ namespace FrontEnd
foreach (var cam in cams) foreach (var cam in cams)
{ {
// Create a cam marker on the canvas map...
CreateCameraMarker(new Point(cnvMap.Width * cam.X, cnvMap.Height * cam.Y), cam); CreateCameraMarker(new Point(cnvMap.Width * cam.X, cnvMap.Height * cam.Y), cam);
// ...and create a correspondig list item...
ListBoxItem item = new ListBoxItem ListBoxItem item = new ListBoxItem
{ {
Tag = cam, Tag = cam,
@ -144,6 +181,7 @@ namespace FrontEnd
}; };
lstDevices.Items.Add(item); lstDevices.Items.Add(item);
// ...with associated clients as subitems.
foreach (var client in clients.Where(c => c.Id == cam.Client_Id)) foreach (var client in clients.Where(c => c.Id == cam.Client_Id))
{ {
ListBoxItem subitem = new ListBoxItem ListBoxItem subitem = new ListBoxItem
@ -158,6 +196,7 @@ namespace FrontEnd
private void LstDevices_SelectionChanged(object sender, SelectionChangedEventArgs e) private void LstDevices_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
// Show device properties in textbox.
var selectedItem = lstDevices.SelectedItem as ListBoxItem; var selectedItem = lstDevices.SelectedItem as ListBoxItem;
if (selectedItem != null) if (selectedItem != null)
{ {
@ -174,6 +213,7 @@ namespace FrontEnd
private void BtnRefresh_Click(object sender, RoutedEventArgs e) private void BtnRefresh_Click(object sender, RoutedEventArgs e)
{ {
// Reload information on button click.
LoadInformation(); LoadInformation();
} }
} }

View File

@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FrontEnd" xmlns:local="clr-namespace:FrontEnd"
mc:Ignorable="d" mc:Ignorable="d"
Title="StreamWindow" Height="450" Width="800" Loaded="Window_Loaded"> Title="Stream" Height="450" Width="800" Loaded="Window_Loaded">
<Grid> <Grid>
<Image x:Name="imgStream" HorizontalAlignment="Left" Height="399" Margin="10,10,0,0" VerticalAlignment="Top" Width="772"/> <Image x:Name="imgStream" HorizontalAlignment="Left" Height="399" Margin="10,10,0,0" VerticalAlignment="Top" Width="772"/>
</Grid> </Grid>

View File

@ -26,7 +26,6 @@ namespace FrontEnd
InitializeComponent(); InitializeComponent();
} }
public StreamWindow(Cam cam, bool processed) : this() public StreamWindow(Cam cam, bool processed) : this()
{ {
_cam = cam; _cam = cam;
@ -35,8 +34,10 @@ namespace FrontEnd
private void Window_Loaded(object sender, RoutedEventArgs e) private void Window_Loaded(object sender, RoutedEventArgs e)
{ {
// Check if we want the original or processed stream.
string steamAddr = _processed ? Communicator.GetProcessedCameraAddress(_cam) : _cam.Ip; string steamAddr = _processed ? Communicator.GetProcessedCameraAddress(_cam) : _cam.Ip;
// // retrieve single image
//if (_processed) //if (_processed)
//{ //{
// _ = Task.Run(async () => // _ = Task.Run(async () =>
@ -47,6 +48,7 @@ namespace FrontEnd
//} //}
//else //else
// Show stream in image control.
_ = SimpleMJPEGDecoder.StartAsync((BitmapImage img) => _ = SimpleMJPEGDecoder.StartAsync((BitmapImage img) =>
{ {
imgStream.Dispatcher.Invoke(() => { imgStream.Source = img; }); imgStream.Dispatcher.Invoke(() => { imgStream.Source = img; });