diff options
| author | Roy <roy.mail.net@gmail.com> | 2017-11-23 00:37:30 +0200 |
|---|---|---|
| committer | Roy <roy.mail.net@gmail.com> | 2017-11-23 00:37:30 +0200 |
| commit | 14374562c002481b102feb8e25c7036cafb59853 (patch) | |
| tree | df39d0dc72981af63544e0c84eefc8146e3a371a /Software | |
| parent | 62ceb1153be41b798c65c195df11ac329bb9315c (diff) | |
| download | Tango-14374562c002481b102feb8e25c7036cafb59853.tar.gz Tango-14374562c002481b102feb8e25c7036cafb59853.zip | |
Fixed issue with TcpServer Synchronization Context initialization.
Completed Tango Transport Router Utility.
Diffstat (limited to 'Software')
5 files changed, 326 insertions, 22 deletions
diff --git a/Software/Visual_Studio/Tango.Transport/Servers/TcpServer.cs b/Software/Visual_Studio/Tango.Transport/Servers/TcpServer.cs index 8ce79757a..36e0869f3 100644 --- a/Software/Visual_Studio/Tango.Transport/Servers/TcpServer.cs +++ b/Software/Visual_Studio/Tango.Transport/Servers/TcpServer.cs @@ -45,7 +45,6 @@ namespace Tango.Transport.Servers public TcpServer(int port) { Port = port; - scheduler = TaskScheduler.FromCurrentSynchronizationContext(); } #endregion @@ -58,6 +57,11 @@ namespace Tango.Transport.Servers { if (!IsStarted) { + if (scheduler == null) + { + scheduler = TaskScheduler.FromCurrentSynchronizationContext(); + } + Listener = new TcpListener(System.Net.IPAddress.Any, Port); Listener.Start(); IsStarted = true; diff --git a/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/MainWindow.xaml b/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/MainWindow.xaml index e94d1657a..001a7f01d 100644 --- a/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/MainWindow.xaml +++ b/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/MainWindow.xaml @@ -9,7 +9,7 @@ xmlns:views="clr-namespace:Tango.TransportRouter.UI.Views" xmlns:local="clr-namespace:Tango.TransportRouter.UI" mc:Ignorable="d" - Title="Tango Transport Router" Height="200" Width="545" TitleCaps="False" BorderBrush="Gray" BorderThickness="1" WindowStartupLocation="CenterScreen" Background="#202020" Foreground="Gainsboro" DataContext="{Binding RelativeSource={RelativeSource Self}}"> + Title="Tango Transport Router" Height="220" Width="545" ResizeMode="CanMinimize" TitleCaps="False" BorderBrush="Gray" BorderThickness="1" WindowStartupLocation="CenterScreen" Background="#202020" Foreground="Gainsboro" DataContext="{Binding RelativeSource={RelativeSource Self}}"> <Grid Margin="10"> <views:MainView DataContext="{StaticResource MainViewVM}"></views:MainView> </Grid> diff --git a/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/Tango.TransportRouter.UI.csproj b/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/Tango.TransportRouter.UI.csproj index eb749873a..d05260a72 100644 --- a/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/Tango.TransportRouter.UI.csproj +++ b/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/Tango.TransportRouter.UI.csproj @@ -18,7 +18,7 @@ <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> - <OutputPath>..\Build\Debug\</OutputPath> + <OutputPath>..\..\Build\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> diff --git a/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/ViewModels/MainViewVM.cs b/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/ViewModels/MainViewVM.cs index 87498c55c..a98f2fa7b 100644 --- a/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/ViewModels/MainViewVM.cs @@ -2,9 +2,13 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; +using System.Windows; +using System.Windows.Threading; using Tango.SharedUI; using Tango.SharedUI.Commands; +using Tango.Transport.Adapters; using Tango.Transport.Routing; using Tango.Transport.Servers; @@ -12,37 +16,187 @@ namespace Tango.TransportRouter.UI.ViewModels { public class MainViewVM : ExtendedObject { - private SimpleTransportRouter _router; + private TransportRoutingChannel _channel; private TcpServer _server; + private UsbTransportAdapter _usbAdapter; + private TcpTransportAdapter _tcpAdapter; - public RelayCommand StartCommand { get; set; } + #region Properties - public RelayCommand StopCommand { get; set; } + /// <summary> + /// Gets or sets the usb ports. + /// </summary> + public List<String> UsbPorts { get; set; } + + private String _selectedUsbPort; + /// <summary> + /// Gets or sets the selected USB port. + /// </summary> + public String SelectedUsbPort + { + get { return _selectedUsbPort; } + set { _selectedUsbPort = value; RaisePropertyChanged(nameof(SelectedUsbPort)); } + } + + private bool _isStarted; + /// <summary> + /// Gets or sets a value indicating whether this instance is started. + /// </summary> + public bool IsStarted + { + get { return _isStarted; } + set { _isStarted = value; RaisePropertyChanged(nameof(IsStarted)); } + } + + private bool _isWaitingForTCP; + /// <summary> + /// Gets or sets a value indicating whether this instance is waiting for TCP. + /// </summary> + public bool IsWaitingForTCP + { + get { return _isWaitingForTCP; } + set { _isWaitingForTCP = value; RaisePropertyChanged(nameof(IsWaitingForTCP)); } + } + + private bool _tcpOn; + + public bool TcpOn + { + get { return _tcpOn; } + set { _tcpOn = value; RaisePropertyChanged(nameof(TcpOn)); } + } + + private bool _usbOn; + + public bool UsbOn + { + get { return _usbOn; } + set { _usbOn = value; RaisePropertyChanged(nameof(UsbOn)); } + } + + + #endregion + + #region Commands + + /// <summary> + /// Gets or sets the toggle start stop command. + /// </summary> + public RelayCommand ToggleStartStopCommand { get; set; } + + #endregion public MainViewVM() { _server = new TcpServer(9999); - _router = new SimpleTransportRouter(); - StartCommand = new RelayCommand(Start); - StopCommand = new RelayCommand(Stop); + ToggleStartStopCommand = new RelayCommand(ToggleStartStop); _server.ClientConnected += _server_ClientConnected; + + UsbPorts = Enumerable.Range(1, 9).Select(x => "COM" + x).ToList(); + SelectedUsbPort = UsbPorts.First(); + + + } + + private void ToggleStartStop() + { + if (IsStarted) + { + Stop(); + } + else + { + Start(); + } + } + + private async void Stop() + { + try + { + _server.Stop(); + + if (_tcpAdapter != null) + { + await _tcpAdapter.Disconnect(); + } + + await _usbAdapter.Disconnect(); + IsStarted = false; + IsWaitingForTCP = false; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + + private async void Start() + { + try + { + _usbAdapter = new UsbTransportAdapter(SelectedUsbPort); + _server.Start(); + await _usbAdapter.Connect(); + IsStarted = true; + IsWaitingForTCP = true; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + + private async void _server_ClientConnected(object sender, ClientConnectedEventArgs e) + { + IsWaitingForTCP = false; + + _tcpAdapter = new TcpTransportAdapter(e.Socket); + await _tcpAdapter.Connect(); + + _channel = new TransportRoutingChannel(_usbAdapter, _tcpAdapter); + + _usbAdapter.DataAvailable -= _usbAdapter_DataAvailable; + _tcpAdapter.DataAvailable -= _tcpAdapter_DataAvailable; + _usbAdapter.DataAvailable += _usbAdapter_DataAvailable; + _tcpAdapter.DataAvailable += _tcpAdapter_DataAvailable; } - private void Stop(object obj) + private void _tcpAdapter_DataAvailable(object sender, byte[] e) { - throw new NotImplementedException(); + InvokeUI(() => + { + TcpOn = true; + DispatcherTimer timer = new DispatcherTimer(); + timer.Interval = TimeSpan.FromMilliseconds(100); + timer.Tick += (x, y) => + { + TcpOn = false; timer.Stop(); + }; + timer.Start(); + }); } - private void Start(object obj) + private void _usbAdapter_DataAvailable(object sender, byte[] e) { - throw new NotImplementedException(); + InvokeUI(() => + { + UsbOn = true; + DispatcherTimer timer = new DispatcherTimer(); + timer.Interval = TimeSpan.FromMilliseconds(100); + timer.Tick += (x, y) => + { + UsbOn = false; timer.Stop(); + }; + timer.Start(); + }); } - private void _server_ClientConnected(object sender, ClientConnectedEventArgs e) + private void InvokeUI(Action action) { - throw new NotImplementedException(); + Application.Current.Dispatcher.BeginInvoke(action); } } } diff --git a/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/Views/MainView.xaml b/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/Views/MainView.xaml index 2d0b9d57a..07a4a963e 100644 --- a/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/Utilities/Tango.TransportRouter.UI/Views/MainView.xaml @@ -2,11 +2,20 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" + xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls" xmlns:fa="http://schemas.fontawesome.io/icons/" xmlns:local="clr-namespace:Tango.TransportRouter.UI.Views" mc:Ignorable="d" - d:DesignHeight="200" d:DesignWidth="545" Background="#202020"> + d:DesignHeight="170" d:DesignWidth="545" Background="#202020"> + + <UserControl.Resources> + <SolidColorBrush Color="#42C300" x:Key="on"></SolidColorBrush> + <converters:BooleanToVisibilityInverseConverter x:Key="BooleanToVisibilityInverseConverter"></converters:BooleanToVisibilityInverseConverter> + <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></converters:BooleanToVisibilityConverter> + </UserControl.Resources> + <Grid> <Grid> <Grid.RowDefinitions> @@ -47,16 +56,85 @@ <ColumnDefinition/> </Grid.ColumnDefinitions> - <Ellipse Grid.Column="0" Width="16" Height="16" Fill="Black"></Ellipse> - <Ellipse Grid.Column="1" Width="16" Height="16" Fill="Black"></Ellipse> + <Ellipse Grid.Column="0" Width="16" Height="16"> + <Ellipse.Style> + <Style TargetType="Ellipse"> + <Setter Property="Fill" Value="Black"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding TcpOn}" Value="True"> + <DataTrigger.EnterActions> + <BeginStoryboard> + <Storyboard> + <ColorAnimation BeginTime="00:00:0.15" Storyboard.TargetProperty="Fill.Color" From="Black" To="Lime" Duration="00:00:0.05" AutoReverse="True"></ColorAnimation> + </Storyboard> + </BeginStoryboard> + </DataTrigger.EnterActions> + </DataTrigger> + <DataTrigger Binding="{Binding UsbOn}" Value="True"> + <DataTrigger.EnterActions> + <BeginStoryboard> + <Storyboard> + <ColorAnimation BeginTime="00:00:0.0" Storyboard.TargetProperty="Fill.Color" From="Black" To="Lime" Duration="00:00:0.05" AutoReverse="True"></ColorAnimation> + </Storyboard> + </BeginStoryboard> + </DataTrigger.EnterActions> + </DataTrigger> + </Style.Triggers> + </Style> + </Ellipse.Style> + </Ellipse> + <Ellipse Grid.Column="1" Width="16" Height="16"> + <Ellipse.Style> + <Style TargetType="Ellipse"> + <Setter Property="Fill" Value="Black"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding TcpOn}" Value="True"> + <DataTrigger.EnterActions> + <BeginStoryboard> + <Storyboard> + <ColorAnimation BeginTime="00:00:0.10" Storyboard.TargetProperty="Fill.Color" From="Black" To="Lime" Duration="00:00:0.05" AutoReverse="True"></ColorAnimation> + </Storyboard> + </BeginStoryboard> + </DataTrigger.EnterActions> + </DataTrigger> + <DataTrigger Binding="{Binding UsbOn}" Value="True"> + <DataTrigger.EnterActions> + <BeginStoryboard> + <Storyboard> + <ColorAnimation BeginTime="00:00:0.05" Storyboard.TargetProperty="Fill.Color" From="Black" To="Lime" Duration="00:00:0.05" AutoReverse="True"></ColorAnimation> + </Storyboard> + </BeginStoryboard> + </DataTrigger.EnterActions> + </DataTrigger> + </Style.Triggers> + </Style> + </Ellipse.Style> + </Ellipse> <Rectangle Grid.Column="1" Width="18" Height="24" HorizontalAlignment="Right" Margin="0 0 -18 0" Fill="DimGray"></Rectangle> <Rectangle Grid.Column="0" Width="18" Height="24" HorizontalAlignment="Left" Margin="-18 0 0 0" Fill="DimGray"></Rectangle> </Grid> + + <ComboBox Visibility="{Binding IsStarted,Converter={StaticResource BooleanToVisibilityInverseConverter}}" ItemsSource="{Binding UsbPorts}" SelectedItem="{Binding SelectedUsbPort,Mode=TwoWay}" VerticalAlignment="Bottom" VerticalContentAlignment="Center" FontSize="12" Foreground="Yellow" BorderThickness="0" Background="Transparent" HorizontalAlignment="Center" Width="100" Margin="10"></ComboBox> </Grid> <Grid Grid.Column="1"> - <fa:ImageAwesome Icon="PowerOff" Width="80" Height="80" Foreground="DimGray" Cursor="Hand"></fa:ImageAwesome> + <Button Cursor="Hand" Width="90" Height="90" Style="{DynamicResource MetroCircleButtonStyle}" mahapps:ButtonHelper.PreserveTextCase="True" BorderThickness="0" Command="{Binding ToggleStartStopCommand}"> + <StackPanel Orientation="Horizontal"> + <fa:ImageAwesome Icon="PowerOff" Width="80" Height="80" Cursor="Hand"> + <fa:ImageAwesome.Style> + <Style TargetType="fa:ImageAwesome"> + <Setter Property="Foreground" Value="DimGray"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding IsStarted}" Value="True"> + <Setter Property="Foreground" Value="#49C906"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </fa:ImageAwesome.Style> + </fa:ImageAwesome> + </StackPanel> + </Button> </Grid> <Grid Grid.Column="2"> @@ -67,11 +145,79 @@ <ColumnDefinition/> </Grid.ColumnDefinitions> - <Ellipse Grid.Column="0" Width="16" Height="16" Fill="Black"></Ellipse> - <Ellipse Grid.Column="1" Width="16" Height="16" Fill="Black"></Ellipse> + <Ellipse Grid.Column="0" Width="16" Height="16"> + <Ellipse.Style> + <Style TargetType="Ellipse"> + <Setter Property="Fill" Value="Black"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding TcpOn}" Value="True"> + <DataTrigger.EnterActions> + <BeginStoryboard> + <Storyboard> + <ColorAnimation BeginTime="00:00:0.05" Storyboard.TargetProperty="Fill.Color" From="Black" To="Lime" Duration="00:00:0.05" AutoReverse="True"></ColorAnimation> + </Storyboard> + </BeginStoryboard> + </DataTrigger.EnterActions> + </DataTrigger> + <DataTrigger Binding="{Binding UsbOn}" Value="True"> + <DataTrigger.EnterActions> + <BeginStoryboard> + <Storyboard> + <ColorAnimation BeginTime="00:00:0.10" Storyboard.TargetProperty="Fill.Color" From="Black" To="Lime" Duration="00:00:0.05" AutoReverse="True"></ColorAnimation> + </Storyboard> + </BeginStoryboard> + </DataTrigger.EnterActions> + </DataTrigger> + </Style.Triggers> + </Style> + </Ellipse.Style> + </Ellipse> + <Ellipse Grid.Column="1" Width="16" Height="16"> + <Ellipse.Style> + <Style TargetType="Ellipse"> + <Setter Property="Fill" Value="Black"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding TcpOn}" Value="True"> + <DataTrigger.EnterActions> + <BeginStoryboard> + <Storyboard> + <ColorAnimation Storyboard.TargetProperty="Fill.Color" From="Black" To="Lime" Duration="00:00:0.05" AutoReverse="True"></ColorAnimation> + </Storyboard> + </BeginStoryboard> + </DataTrigger.EnterActions> + </DataTrigger> + <DataTrigger Binding="{Binding UsbOn}" Value="True"> + <DataTrigger.EnterActions> + <BeginStoryboard> + <Storyboard> + <ColorAnimation BeginTime="00:00:0.15" Storyboard.TargetProperty="Fill.Color" From="Black" To="Lime" Duration="00:00:0.05" AutoReverse="True"></ColorAnimation> + </Storyboard> + </BeginStoryboard> + </DataTrigger.EnterActions> + </DataTrigger> + </Style.Triggers> + </Style> + </Ellipse.Style> + </Ellipse> <Rectangle Grid.Column="0" Width="18" Height="24" HorizontalAlignment="Left" Margin="-18 0 0 0" Fill="DimGray"></Rectangle> <Rectangle Grid.Column="1" Width="18" Height="24" HorizontalAlignment="Right" Margin="0 0 -18 0" Fill="DimGray"></Rectangle> </Grid> + + <TextBlock Visibility="{Binding IsWaitingForTCP,Converter={StaticResource BooleanToVisibilityConverter}}" VerticalAlignment="Bottom" Text="Waiting for connection..." HorizontalAlignment="Center" Margin="20" Foreground="DimGray"> + <TextBlock.Style> + <Style TargetType="TextBlock"> + <Style.Triggers> + <EventTrigger RoutedEvent="Loaded"> + <BeginStoryboard> + <Storyboard> + <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" AutoReverse="True" Duration="00:00:0.2" RepeatBehavior="Forever"></DoubleAnimation> + </Storyboard> + </BeginStoryboard> + </EventTrigger> + </Style.Triggers> + </Style> + </TextBlock.Style> + </TextBlock> </Grid> </Grid> </Grid> |
