diff options
| author | Roy Ben-Shabat <Roy@Twine-s.com> | 2017-11-12 16:57:52 +0200 |
|---|---|---|
| committer | Roy Ben-Shabat <Roy@Twine-s.com> | 2017-11-12 16:57:52 +0200 |
| commit | e2822236eebed39637656785a3e7937e85c90cd3 (patch) | |
| tree | bc6b37cee949bf8ff15c358661c69c84db3f336e /Software | |
| parent | 69a7046b956fea30a5efaa291ab6ac3bc57f94cc (diff) | |
| download | Tango-e2822236eebed39637656785a3e7937e85c90cd3.tar.gz Tango-e2822236eebed39637656785a3e7937e85c90cd3.zip | |
Added some features for machine emulator.
Implemented information logs on TranspoterBase!
Diffstat (limited to 'Software')
19 files changed, 418 insertions, 161 deletions
diff --git a/Software/Visual Studio/Tango.Emulations/Emulators/MachineEmulator.cs b/Software/Visual Studio/Tango.Emulations/Emulators/MachineEmulator.cs index c12a60203..b46ee9adf 100644 --- a/Software/Visual Studio/Tango.Emulations/Emulators/MachineEmulator.cs +++ b/Software/Visual Studio/Tango.Emulations/Emulators/MachineEmulator.cs @@ -55,7 +55,7 @@ namespace Tango.Emulations.Emulators Task.Factory.StartNew(() => { Thread.Sleep(2000); - var request = MessageFactory.ParseContainer<CalculateRequest>(container); + var request = MessageFactory.ParseMessageFromContainer<CalculateRequest>(container); var response = MessageFactory.CreateTangoMessage<CalculateResponse>(container.Token); response.Message.Sum = request.A + request.B; Transporter.SendResponse(response); @@ -63,7 +63,7 @@ namespace Tango.Emulations.Emulators break; case MessageType.ProgressRequest: - var r = MessageFactory.ParseContainer<ProgressRequest>(container); + var r = MessageFactory.ParseMessageFromContainer<ProgressRequest>(container); Task.Factory.StartNew(() => { diff --git a/Software/Visual Studio/Tango.PMR/MessageFactory.cs b/Software/Visual Studio/Tango.PMR/MessageFactory.cs index eb7155678..cc36cbf73 100644 --- a/Software/Visual Studio/Tango.PMR/MessageFactory.cs +++ b/Software/Visual Studio/Tango.PMR/MessageFactory.cs @@ -80,7 +80,7 @@ namespace Tango.PMR /// <typeparam name="T"></typeparam> /// <param name="data">The data.</param> /// <returns></returns> - public static T ParseContainer<T>(MessageContainer container) where T : IMessage<T> + public static T ParseMessageFromContainer<T>(MessageContainer container) where T : IMessage<T> { MessageParser<T> parser = new MessageParser<T>(() => Activator.CreateInstance<T>()); return parser.ParseFrom(container.Data); @@ -91,7 +91,7 @@ namespace Tango.PMR /// </summary> /// <param name="container">The container.</param> /// <returns></returns> - public static IMessage ParseContainer(MessageContainer container) + public static IMessage ParseMessageFromContainer(MessageContainer container) { var type = typeof(MessageFactory).Assembly.GetTypes().ToList().SingleOrDefault(x => x.Name == container.Type.ToString()); MessageParser parser = type.GetProperty("Parser").GetValue(container) as MessageParser; @@ -104,7 +104,7 @@ namespace Tango.PMR /// <typeparam name="T"></typeparam> /// <param name="data">The data.</param> /// <returns></returns> - public static MessageContainer ParseContainerPartial(byte[] data) + public static MessageContainer ParseContainer(byte[] data) { MessageContainer container = MessageContainer.Parser.ParseFrom(data); return container; @@ -116,7 +116,7 @@ namespace Tango.PMR /// <typeparam name="T"></typeparam> /// <param name="data">The data.</param> /// <returns></returns> - public static MessageContainer ParseContainerPartialJson(byte[] data) + public static MessageContainer ParseContainerJson(byte[] data) { MessageContainer container = MessageContainer.Parser.ParseJson(Encoding.UTF8.GetString(data)); return container; diff --git a/Software/Visual Studio/Tango.Stubs/StubAttribute.cs b/Software/Visual Studio/Tango.Stubs/StubAttribute.cs index 20fe1dea0..c7611e606 100644 --- a/Software/Visual Studio/Tango.Stubs/StubAttribute.cs +++ b/Software/Visual Studio/Tango.Stubs/StubAttribute.cs @@ -12,10 +12,13 @@ namespace Tango.Stubs public String Description { get; set; } - public StubAttribute(String name, String description) + public StubDirection Direction { get; set; } + + public StubAttribute(String name, String description, StubDirection direction) { Name = name; Description = description; + Direction = direction; } } } diff --git a/Software/Visual Studio/Tango.Stubs/StubBase.cs b/Software/Visual Studio/Tango.Stubs/StubBase.cs index 9270a8702..59acc4c72 100644 --- a/Software/Visual Studio/Tango.Stubs/StubBase.cs +++ b/Software/Visual Studio/Tango.Stubs/StubBase.cs @@ -66,15 +66,19 @@ namespace Tango.Stubs protected abstract Task<String> OnRun(Action<String> multiResponseCallback); - public static List<AvailableStub> GetAvailableStubs() + public static List<AvailableStub> GetAvailableStubs(StubDirection direction) { List<AvailableStub> results = new List<AvailableStub>(); foreach (Type type in Assembly.GetAssembly(typeof(StubBase)).GetTypes().Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(StubBase)))) { StubAttribute att = type.GetCustomAttributes(typeof(StubAttribute), true).FirstOrDefault() as StubAttribute; - AvailableStub availableStub = new AvailableStub(type, att.Name, att.Description); - results.Add(availableStub); + + if (att.Direction == direction) + { + AvailableStub availableStub = new AvailableStub(type, att.Name, att.Description); + results.Add(availableStub); + } } return results; diff --git a/Software/Visual Studio/Tango.Stubs/StubDirection.cs b/Software/Visual Studio/Tango.Stubs/StubDirection.cs new file mode 100644 index 000000000..00406f11c --- /dev/null +++ b/Software/Visual Studio/Tango.Stubs/StubDirection.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Stubs +{ + public enum StubDirection + { + ToMachine, + ToMobile, + } +} diff --git a/Software/Visual Studio/Tango.Stubs/Stubs/Calculate.cs b/Software/Visual Studio/Tango.Stubs/Stubs/Calculate.cs index 50c4c437a..2f5d15e85 100644 --- a/Software/Visual Studio/Tango.Stubs/Stubs/Calculate.cs +++ b/Software/Visual Studio/Tango.Stubs/Stubs/Calculate.cs @@ -11,7 +11,7 @@ using Tango.Transport; namespace Tango.Stubs.Stubs { - [Stub("Calculate", "Calculate two numbers and return the result.")] + [Stub("Calculate", "Calculate two numbers and return the result.", StubDirection.ToMachine)] public class Calculate : StubBase { public Calculate(ITransporter transporter) : base(transporter) diff --git a/Software/Visual Studio/Tango.Stubs/Stubs/Progress.cs b/Software/Visual Studio/Tango.Stubs/Stubs/Progress.cs index c61e61873..91cd1ab6a 100644 --- a/Software/Visual Studio/Tango.Stubs/Stubs/Progress.cs +++ b/Software/Visual Studio/Tango.Stubs/Stubs/Progress.cs @@ -10,7 +10,7 @@ using Tango.Transport; namespace Tango.Stubs.Stubs { - [Stub("Progress", "Check for multiple response request")] + [Stub("Progress", "Check for multiple response request", StubDirection.ToMachine)] public class Progress : StubBase { public Progress(ITransporter transporter) : base(transporter) diff --git a/Software/Visual Studio/Tango.Stubs/Tango.Stubs.csproj b/Software/Visual Studio/Tango.Stubs/Tango.Stubs.csproj index f4dbf9bb4..5dadee0ab 100644 --- a/Software/Visual Studio/Tango.Stubs/Tango.Stubs.csproj +++ b/Software/Visual Studio/Tango.Stubs/Tango.Stubs.csproj @@ -49,6 +49,7 @@ <Compile Include="AvailableStub.cs" /> <Compile Include="IStub.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="StubDirection.cs" /> <Compile Include="Stubs\Progress.cs" /> <Compile Include="Stubs\Calculate.cs" /> <Compile Include="StubAttribute.cs" /> diff --git a/Software/Visual Studio/Tango.Transport/TransportMessage.cs b/Software/Visual Studio/Tango.Transport/TransportMessage.cs index 4f864f9f6..0f8414333 100644 --- a/Software/Visual Studio/Tango.Transport/TransportMessage.cs +++ b/Software/Visual Studio/Tango.Transport/TransportMessage.cs @@ -1,8 +1,10 @@ -using System; +using Google.Protobuf; +using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Tango.PMR; namespace Tango.Transport { diff --git a/Software/Visual Studio/Tango.Transport/TransporterBase.cs b/Software/Visual Studio/Tango.Transport/TransporterBase.cs index 9090bbfa2..c0c9fa72f 100644 --- a/Software/Visual Studio/Tango.Transport/TransporterBase.cs +++ b/Software/Visual Studio/Tango.Transport/TransporterBase.cs @@ -95,8 +95,12 @@ namespace Tango.Transport /// <param name="e">The <see cref="System.Collections.Specialized.NotifyCollectionChangedEventArgs"/> instance containing the event data.</param> protected virtual async void OnAdaptersCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { + LogManager.Log("Adapters collection changed, Listing adapters:"); + foreach (var ad in _adapters) { + LogManager.Log(ad.GetType().Name + ", " + ad.Address + ", " + ad.State.ToString()); + ad.StateChanged -= OnAdapterStateChanged; ad.StateChanged += OnAdapterStateChanged; ad.DataAvailable -= OnAdapterDataAvailable; @@ -189,9 +193,9 @@ namespace Tango.Transport /// </summary> /// <param name="data">The data.</param> /// <returns></returns> - protected virtual MessageContainer OnParseContainerPartial(byte[] data) + protected virtual MessageContainer OnParseContainer(byte[] data) { - return MessageFactory.ParseContainerPartial(data); + return MessageFactory.ParseContainer(data); } /// <summary> @@ -199,9 +203,9 @@ namespace Tango.Transport /// </summary> /// <param name="container">The container.</param> /// <returns></returns> - protected virtual IMessage OnParseContainer(MessageContainer container) + protected virtual IMessage OnParseMessage(MessageContainer container) { - return MessageFactory.ParseContainer(container); + return MessageFactory.ParseMessageFromContainer(container); } #endregion @@ -279,10 +283,21 @@ namespace Tango.Transport /// <returns></returns> public Task<Response> SendRequest<Request, Response>(TangoMessage<Request> request, ITransportAdapter adapter) where Request : IMessage<Request> where Response : IMessage<Response> { + LogManager.Log("Queuing request message: " + typeof(Request).Name + " on adapter: " + (adapter != null ? adapter.Address : "ALL")); + LogManager.Log("Expected response: " + typeof(Response).Name); + TaskCompletionSource<Response> source = new TaskCompletionSource<Response>(); TransportMessage<Response> message = new TransportMessage<Response>(adapter, request.Container.Token, request, TransportMessageDirection.Request, OnSerializeingMessage(request), source); _sendingQueue.Enqueue(message); - Task.Delay(RequestTimeout).ContinueWith((x) => { if (!source.Task.IsCompleted) source.SetException(new TimeoutException()); }); + Task.Delay(RequestTimeout).ContinueWith((x) => + { + if (!source.Task.IsCompleted) + { + LogManager.Log("Request message: " + typeof(Response).Name + " had timed out after " + RequestTimeout.TotalSeconds + " seconds."); + LogManager.Log("Setting request task exception..."); + source.SetException(new TimeoutException()); + } + }); return source.Task; } @@ -308,6 +323,9 @@ namespace Tango.Transport /// <param name="responseCallback">The response callback delegate.</param> public void SendMultiRequest<Request, Response>(TangoMessage<Request> request, ITransportAdapter adapter, Action<Response> responseCallback) where Request : IMessage<Request> where Response : IMessage<Response> { + LogManager.Log("Queuing multi response request message: " + typeof(Request).Name + " on adapter: " + (adapter != null ? adapter.Address : "ALL")); + LogManager.Log("Expected response: " + typeof(Response).Name); + TransportMessage<Response> message = new TransportMessage<Response>(adapter, request.Container.Token, request, TransportMessageDirection.Request, OnSerializeingMessage(request), null) { IsMultiResponse = true, @@ -324,12 +342,22 @@ namespace Tango.Transport /// <returns></returns> public Task SendResponse<Response>(TangoMessage<Response> response) where Response : IMessage<Response> { + LogManager.Log("Queuing response message: " + typeof(Response).Name); + ITransportAdapter adapter = null; + LogManager.Log("Searching for matching request token..."); + if (_tokenAdapters.TryGetValue(response.Container.Token, out adapter)) { + LogManager.Log("Found matching request token: " + response.Container.Token + " on adapter: " + (adapter != null ? adapter.Address : "ALL")); + LogManager.Log("Removing matching request token."); _tokenAdapters.Remove(response.Container.Token); } + else + { + LogManager.Log("Matching request token was not found..."); + } TaskCompletionSource<object> source = new TaskCompletionSource<object>(); TransportMessage<object> message = new TransportMessage<object>(adapter, response.Container.Token, response, TransportMessageDirection.Response, OnSerializeingMessage(response), source); @@ -431,46 +459,62 @@ namespace Tango.Transport { if (_arrivedResponses.TryDequeue(out data)) { - MessageContainer container = OnParseContainerPartial(data.Value); + LogManager.Log("Message received on adapter: " + data.Key.Address); + + LogManager.Log("Parsing message container..."); + MessageContainer container = OnParseContainer(data.Value); + LogManager.Log("Searching for pending request token: " + container.Token); TransportMessageBase request = _pendingRequests.SingleOrDefault(x => x.Token == container.Token); if (request != null) { + LogManager.Log("Found pending request: " + request.Message.GetType().GetGenericArguments()[0].Name); + if (!request.IsMultiResponse) { + LogManager.Log("Pending request was identified as 'single response'. Removing pending request."); + _pendingRequests.Remove(request); try { - request.SetResult(OnParseContainer(container)); + LogManager.Log("Parsing inner response message and setting pending request task result..."); + request.SetResult(OnParseMessage(container)); } catch (Exception ex) { - request.SetException(ex); + request.SetException(LogManager.Log(ex,"Error parsing inner message.")); } } else { + LogManager.Log("Pending request was identified as 'multi response'. keeping pending request."); + try { - request.InvokeResponseCallback(OnParseContainer(container)); + LogManager.Log("Parsing inner response message and invoking multi response callback..."); + request.InvokeResponseCallback(OnParseMessage(container)); } catch (Exception ex) { - throw ex; + LogManager.Log(ex, "Error parsing inner message."); } } } else { + LogManager.Log("Message was identified as a new request message: " + container.Type.ToString()); + try { + LogManager.Log("Saving request token and adapter: " + container.Token + ", " + data.Key.Address); _tokenAdapters.Add(container.Token, data.Key); - OnRequestReceived(container); + LogManager.Log("Invoking RequestReceived event..."); + Task.Factory.StartNew(() => OnRequestReceived(container)); } - catch (Exception ex) + catch { - throw ex; + //Ignore any exception that might occur on the event handler side... } } } diff --git a/Software/Visual Studio/Tango.Transport/Transporters/JsonTransporter.cs b/Software/Visual Studio/Tango.Transport/Transporters/JsonTransporter.cs index 67756d39c..d490d4a61 100644 --- a/Software/Visual Studio/Tango.Transport/Transporters/JsonTransporter.cs +++ b/Software/Visual Studio/Tango.Transport/Transporters/JsonTransporter.cs @@ -52,9 +52,9 @@ namespace Tango.Transport.Transporters /// </summary> /// <param name="data">The data.</param> /// <returns></returns> - protected override MessageContainer OnParseContainerPartial(byte[] data) + protected override MessageContainer OnParseContainer(byte[] data) { - return MessageFactory.ParseContainerPartialJson(data); + return MessageFactory.ParseContainerJson(data); } } } diff --git a/Software/Visual Studio/Utilities/Tango.MachineEM.UI/App.xaml b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/App.xaml index a2db7a7c0..f43a3b797 100644 --- a/Software/Visual Studio/Utilities/Tango.MachineEM.UI/App.xaml +++ b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/App.xaml @@ -1,6 +1,7 @@ <Application x:Class="Tango.MachineEM.UI.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:vm="clr-namespace:Tango.MachineEM.UI.ViewModels" xmlns:local="clr-namespace:Tango.MachineEM.UI" StartupUri="MainWindow.xaml"> <Application.Resources> @@ -14,6 +15,11 @@ <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Red.xaml" /> <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" /> <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/FlatButton.xaml" /> + + <!--View Models--> + <ResourceDictionary> + <vm:MainViewVM x:Key="MainViewVM" /> + </ResourceDictionary> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> diff --git a/Software/Visual Studio/Utilities/Tango.MachineEM.UI/MainWindow.xaml b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/MainWindow.xaml index 28ad0ca6c..318a4133e 100644 --- a/Software/Visual Studio/Utilities/Tango.MachineEM.UI/MainWindow.xaml +++ b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/MainWindow.xaml @@ -7,58 +7,10 @@ xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" xmlns:fa="http://schemas.fontawesome.io/icons/" xmlns:local="clr-namespace:Tango.MachineEM.UI" + xmlns:views="clr-namespace:Tango.MachineEM.UI.Views" mc:Ignorable="d" Title="Tango Machine Emulator" Height="720" Width="1200" TitleCaps="False" BorderBrush="Gray" BorderThickness="1" WindowStartupLocation="CenterScreen" Background="#202020" Foreground="Gainsboro" DataContext="{Binding RelativeSource={RelativeSource Self}}"> <Grid> - <Grid> - <Grid.RowDefinitions> - <RowDefinition Height="100"/> - <RowDefinition Height="1*"/> - </Grid.RowDefinitions> - - <Grid> - <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="20 15"> - <Image Source="Images/machine-trans.png" RenderOptions.BitmapScalingMode="Fant"></Image> - <TextBlock Text="Tango Machine Emulator" VerticalAlignment="Center" Margin="20 0 0 0" FontSize="36" Foreground="Yellow"> - <TextBlock.Effect> - <DropShadowEffect/> - </TextBlock.Effect> - </TextBlock> - </StackPanel> - - <Rectangle VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Margin="20 0 50 0" Stroke="DimGray" StrokeThickness="1" StrokeDashArray="5"></Rectangle> - </Grid> - - <Grid Grid.Row="1" Margin="20"> - <Grid> - <Grid.RowDefinitions> - <RowDefinition Height="1*"/> - <RowDefinition Height="70"/> - </Grid.RowDefinitions> - - <Grid x:Name="gridContent" Background="#151515" Margin="5"> - <Grid> - - </Grid> - </Grid> - <Grid x:Name="gridActions" Grid.Row="1" Background="#151515" Margin="5"> - <StackPanel HorizontalAlignment="Right" Orientation="Horizontal" Margin="5"> - <Button Margin="5" MinWidth="100" Style="{StaticResource AccentedSquareButtonStyle}" mahapps:ButtonHelper.PreserveTextCase="True" BorderThickness="0" Command="{Binding StopCommand}"> - <StackPanel Orientation="Horizontal"> - <fa:ImageAwesome Icon="Stop" Width="16"></fa:ImageAwesome> - <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">STOP</TextBlock> - </StackPanel> - </Button> - <Button Margin="5" MinWidth="100" Style="{StaticResource AccentedSquareButtonStyle}" mahapps:ButtonHelper.PreserveTextCase="True" BorderThickness="0" Command="{Binding StartCommand}"> - <StackPanel Orientation="Horizontal"> - <fa:ImageAwesome Icon="Play" Width="16"></fa:ImageAwesome> - <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">START</TextBlock> - </StackPanel> - </Button> - </StackPanel> - </Grid> - </Grid> - </Grid> - </Grid> + <views:MainView DataContext="{StaticResource MainViewVM}"></views:MainView> </Grid> </mahapps:MetroWindow> diff --git a/Software/Visual Studio/Utilities/Tango.MachineEM.UI/MainWindow.xaml.cs b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/MainWindow.xaml.cs index a3b49d726..7baded308 100644 --- a/Software/Visual Studio/Utilities/Tango.MachineEM.UI/MainWindow.xaml.cs +++ b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/MainWindow.xaml.cs @@ -13,12 +13,7 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; -using Tango.Emulations.Emulators; using Tango.Logging; -using Tango.SharedUI.Commands; -using Tango.Transport.Adapters; -using Tango.Transport.Servers; -using Tango.Transport.Transporters; namespace Tango.MachineEM.UI { @@ -27,89 +22,12 @@ namespace Tango.MachineEM.UI /// </summary> public partial class MainWindow : MetroWindow { - private TcpServer TcpServer; - - #region Properties - - /// <summary> - /// Gets or sets a value indicating whether the emulator is started. - /// </summary> - public bool IsStarted - { - get { return (bool)GetValue(IsStartedProperty); } - set { SetValue(IsStartedProperty, value); } - } - public static readonly DependencyProperty IsStartedProperty = - DependencyProperty.Register("IsStarted", typeof(bool), typeof(MainWindow), new PropertyMetadata(false)); - - /// <summary> - /// Gets or sets the emulator. - /// </summary> - public MachineEmulator Emulator - { - get { return (MachineEmulator)GetValue(EmulatorProperty); } - set { SetValue(EmulatorProperty, value); } - } - public static readonly DependencyProperty EmulatorProperty = - DependencyProperty.Register("Emulator", typeof(MachineEmulator), typeof(MainWindow), new PropertyMetadata(null)); - - #endregion - - #region Commands - - /// <summary> - /// Gets or sets the start command. - /// </summary> - public RelayCommand StartCommand { get; set; } - - /// <summary> - /// Gets or sets the stop command. - /// </summary> - public RelayCommand StopCommand { get; set; } - - #endregion - /// <summary> /// Initializes a new instance of the <see cref="MainWindow"/> class. /// </summary> public MainWindow() { - LogManager.RegisterLogger(new VSOutputLogger()); - TcpServer = new TcpServer(9999); - TcpServer.ClientConnected += TcpServer_ClientConnected; - - Emulator = new MachineEmulator(new ProtoTransporter()); - - StartCommand = new RelayCommand(async () => - { - await Emulator.Start(); - TcpServer.Start(); - StopCommand.RaiseCanExecuteChanged(); - StartCommand.RaiseCanExecuteChanged(); - }, x => !TcpServer.IsStarted); - - StopCommand = new RelayCommand(async () => - { - TcpServer.Stop(); - await Emulator.Stop(); - StartCommand.RaiseCanExecuteChanged(); - StopCommand.RaiseCanExecuteChanged(); - }, (x) => - { - return TcpServer.IsStarted; - }); - InitializeComponent(); } - - /// <summary> - /// Handles the ClientConnected event of the TcpServer control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="ClientConnectedEventArgs"/> instance containing the event data.</param> - private void TcpServer_ClientConnected(object sender, ClientConnectedEventArgs e) - { - Emulator.Transporter.Adapters.Add(new TcpTransportAdapter(e.Socket)); - } } } diff --git a/Software/Visual Studio/Utilities/Tango.MachineEM.UI/Tango.MachineEM.UI.csproj b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/Tango.MachineEM.UI.csproj index 3d4d51d1a..3f6c9c657 100644 --- a/Software/Visual Studio/Utilities/Tango.MachineEM.UI/Tango.MachineEM.UI.csproj +++ b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/Tango.MachineEM.UI.csproj @@ -66,6 +66,10 @@ <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> </ApplicationDefinition> + <Compile Include="ViewModels\MainViewVM.cs" /> + <Compile Include="Views\MainView.xaml.cs"> + <DependentUpon>MainView.xaml</DependentUpon> + </Compile> <Page Include="MainWindow.xaml"> <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> @@ -78,6 +82,10 @@ <DependentUpon>MainWindow.xaml</DependentUpon> <SubType>Code</SubType> </Compile> + <Page Include="Views\MainView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> </ItemGroup> <ItemGroup> <Compile Include="Properties\AssemblyInfo.cs"> diff --git a/Software/Visual Studio/Utilities/Tango.MachineEM.UI/ViewModels/MainViewVM.cs b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/ViewModels/MainViewVM.cs new file mode 100644 index 000000000..eb8621152 --- /dev/null +++ b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/ViewModels/MainViewVM.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Emulations.Emulators; +using Tango.Logging; +using Tango.SharedUI; +using Tango.SharedUI.Commands; +using Tango.Transport.Adapters; +using Tango.Transport.Servers; +using Tango.Transport.Transporters; + +namespace Tango.MachineEM.UI.ViewModels +{ + public class MainViewVM : ExtendedObject + { + private TcpServer TcpServer; + + #region Properties + + private MachineEmulator _emulator; + /// <summary> + /// Gets or sets the machine emulator. + /// </summary> + public MachineEmulator Emulator + { + get { return _emulator; } + set { _emulator = value; RaisePropertyChanged(nameof(Emulator)); } + } + + private String _log; + /// <summary> + /// Gets or sets the log. + /// </summary> + public String Log + { + get { return _log; } + set { _log = value; RaisePropertyChanged(nameof(Log)); } + } + + #endregion + + #region Commands + + /// <summary> + /// Gets or sets the start command. + /// </summary> + public RelayCommand StartCommand { get; set; } + + /// <summary> + /// Gets or sets the stop command. + /// </summary> + public RelayCommand StopCommand { get; set; } + + #endregion + + #region Constructors + + /// <summary> + /// Initializes a new instance of the <see cref="MainViewVM"/> class. + /// </summary> + public MainViewVM() + { + MainViewLogger logger = new MainViewLogger(); + logger.NewLog += (output) => + { + Log += output + Environment.NewLine; + }; + + LogManager.RegisterLogger(logger); + + Emulator = new MachineEmulator(new ProtoTransporter()); + + StartCommand = new RelayCommand(Start, (x) => !Emulator.IsStarted); + StopCommand = new RelayCommand(Stop,(x) => Emulator.IsStarted); + } + + #endregion + + #region Event Handlers + + /// <summary> + /// Handles the ClientConnected event of the TcpServer control. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="ClientConnectedEventArgs"/> instance containing the event data.</param> + private void TcpServer_ClientConnected(object sender, ClientConnectedEventArgs e) + { + Emulator.Transporter.Adapters.Add(new TcpTransportAdapter(e.Socket)); + } + + #endregion + + #region Command Handlers + + /// <summary> + /// Stops the TCP server and emulator. + /// </summary> + private async void Start() + { + TcpServer = new TcpServer(9999); + TcpServer.ClientConnected += TcpServer_ClientConnected; + TcpServer.Start(); + await Emulator.Start(); + InvalidateRelayCommands(); + } + + /// <summary> + /// Starts the TCP server/USB and emulator. + /// </summary> + private async void Stop() + { + TcpServer.Stop(); + await Emulator.Stop(); + InvalidateRelayCommands(); + } + + #endregion + + #region Custom Logger + + public class MainViewLogger : ILogger + { + public bool Enabled { get; set; } + public bool Immediate { get; set; } + public event Action<String> NewLog; + + public MainViewLogger() + { + Enabled = true; + Immediate = true; + } + + public void OnError(LogItemBase output) + { + NewLog?.Invoke(output.ToString()); + } + + public void OnTrace(LogItemBase output) + { + NewLog?.Invoke(output.ToString()); + } + } + + #endregion + } +} diff --git a/Software/Visual Studio/Utilities/Tango.MachineEM.UI/Views/MainView.xaml b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/Views/MainView.xaml new file mode 100644 index 000000000..d9156eaec --- /dev/null +++ b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/Views/MainView.xaml @@ -0,0 +1,124 @@ +<UserControl x:Class="Tango.MachineEM.UI.Views.MainView" + 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:mahapps="http://metro.mahapps.com/winfx/xaml/controls" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" + xmlns:fa="http://schemas.fontawesome.io/icons/" + xmlns:local="clr-namespace:Tango.MachineEM.UI.Views" + mc:Ignorable="d" + d:DesignHeight="720" d:DesignWidth="1000" Foreground="Gainsboro"> + <Grid> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="100"/> + <RowDefinition Height="1*"/> + </Grid.RowDefinitions> + + <Grid> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="20 15"> + <Image Source="/Images/machine-trans.png" RenderOptions.BitmapScalingMode="Fant"></Image> + <TextBlock Text="Tango Machine Emulator" VerticalAlignment="Center" Margin="20 0 0 0" FontSize="36" Foreground="Yellow"> + <TextBlock.Effect> + <DropShadowEffect/> + </TextBlock.Effect> + </TextBlock> + </StackPanel> + + <Rectangle VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Margin="20 0 50 0" Stroke="DimGray" StrokeThickness="1" StrokeDashArray="5"></Rectangle> + </Grid> + + <Grid Grid.Row="1" Margin="20"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="1*"/> + <RowDefinition Height="70"/> + </Grid.RowDefinitions> + + <Grid x:Name="gridContent" Background="#151515" Margin="5"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="300" /> + <ColumnDefinition Width="1*"/> + </Grid.ColumnDefinitions> + + <Grid Background="#181818"> + <Grid Margin="10 0 10 0"> + <Grid.RowDefinitions> + <RowDefinition Height="40"/> + <RowDefinition Height="346*"/> + <RowDefinition Height="70"/> + </Grid.RowDefinitions> + + <TextBlock VerticalAlignment="Center" FontSize="16">STUBS</TextBlock> + + <ListBox Grid.Row="1"> + + </ListBox> + + <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right"> + <Button Cursor="Hand" Width="50" Height="50" VerticalAlignment="Center" Style="{DynamicResource MetroCircleButtonStyle}" mahapps:ButtonHelper.PreserveTextCase="True" BorderThickness="0" Command="{Binding ClearCommand}"> + <StackPanel Orientation="Horizontal"> + <fa:ImageAwesome Icon="Refresh" Foreground="Gainsboro" Width="24"></fa:ImageAwesome> + </StackPanel> + </Button> + <Button Cursor="Hand" Width="50" Height="50" VerticalAlignment="Center" Style="{DynamicResource MetroCircleButtonStyle}" mahapps:ButtonHelper.PreserveTextCase="True" BorderThickness="0" Command="{Binding CancelCommand}"> + <StackPanel Orientation="Horizontal"> + <fa:ImageAwesome Icon="Stop" Foreground="Red" Width="24"></fa:ImageAwesome> + </StackPanel> + </Button> + <Button Cursor="Hand" Width="50" Height="50" VerticalAlignment="Center" Style="{DynamicResource MetroCircleButtonStyle}" mahapps:ButtonHelper.PreserveTextCase="True" BorderThickness="0" Command="{Binding RunCommand}"> + <StackPanel Orientation="Horizontal"> + <fa:ImageAwesome Icon="Play" Width="24" Foreground="LimeGreen"></fa:ImageAwesome> + </StackPanel> + </Button> + </StackPanel> + </Grid> + </Grid> + + <Grid Grid.Column="1"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="107*"/> + <RowDefinition Height="60*"/> + </Grid.RowDefinitions> + <Grid Grid.Row="1"> + <Grid.RowDefinitions> + <RowDefinition Height="30"/> + <RowDefinition Height="1*"/> + </Grid.RowDefinitions> + + <Border Background="#202020" Padding="5" CornerRadius="10 0 0 10"> + <TextBlock FontSize="16" VerticalAlignment="Center">LOG</TextBlock> + </Border> + + <Grid Grid.Row="1"> + <TextBox x:Name="txtResponse" TextChanged="txtResponse_TextChanged" Text="{Binding Log}" Background="Black" AcceptsReturn="True" TextWrapping="Wrap" VerticalScrollBarVisibility="Visible" BorderThickness="0" Padding="5" FontSize="11" Foreground="Gainsboro"></TextBox> + </Grid> + </Grid> + </Grid> + </Grid> + </Grid> + </Grid> + <Grid x:Name="gridActions" Grid.Row="1" Background="#151515" Margin="5"> + <StackPanel HorizontalAlignment="Right" Orientation="Horizontal" Margin="5"> + <Button Margin="5" MinWidth="100" Style="{StaticResource AccentedSquareButtonStyle}" mahapps:ButtonHelper.PreserveTextCase="True" BorderThickness="0" Command="{Binding StopCommand}"> + <StackPanel Orientation="Horizontal"> + <fa:ImageAwesome Icon="Stop" Width="16"></fa:ImageAwesome> + <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">STOP</TextBlock> + </StackPanel> + </Button> + <Button Margin="5" MinWidth="100" Style="{StaticResource AccentedSquareButtonStyle}" mahapps:ButtonHelper.PreserveTextCase="True" BorderThickness="0" Command="{Binding StartCommand}"> + <StackPanel Orientation="Horizontal"> + <fa:ImageAwesome Icon="Play" Width="16"></fa:ImageAwesome> + <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">START</TextBlock> + </StackPanel> + </Button> + </StackPanel> + </Grid> + </Grid> + </Grid> + </Grid> + </Grid> +</UserControl> diff --git a/Software/Visual Studio/Utilities/Tango.MachineEM.UI/Views/MainView.xaml.cs b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/Views/MainView.xaml.cs new file mode 100644 index 000000000..321852082 --- /dev/null +++ b/Software/Visual Studio/Utilities/Tango.MachineEM.UI/Views/MainView.xaml.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.MachineEM.UI.Views +{ + /// <summary> + /// Interaction logic for MainView.xaml + /// </summary> + public partial class MainView : UserControl + { + public MainView() + { + InitializeComponent(); + } + + private void txtResponse_TextChanged(object sender, TextChangedEventArgs e) + { + txtResponse.ScrollToEnd(); + } + } +} diff --git a/Software/Visual Studio/Utilities/Tango.MobileEM.UI/ViewModels/StubsViewVM.cs b/Software/Visual Studio/Utilities/Tango.MobileEM.UI/ViewModels/StubsViewVM.cs index 480ba1c7c..dc17d5cdc 100644 --- a/Software/Visual Studio/Utilities/Tango.MobileEM.UI/ViewModels/StubsViewVM.cs +++ b/Software/Visual Studio/Utilities/Tango.MobileEM.UI/ViewModels/StubsViewVM.cs @@ -27,7 +27,7 @@ namespace Tango.MobileEM.UI.ViewModels public StubsViewVM() { - AvailableStubs = StubBase.GetAvailableStubs(); + AvailableStubs = StubBase.GetAvailableStubs(StubDirection.ToMachine); } private void OnStubSelected(AvailableStub availableStub) |
