From 2ea2bb5bcd96045f1bd6cb4c3d8b8416dbaa05dc Mon Sep 17 00:00:00 2001 From: Roy Date: Tue, 26 Dec 2017 21:16:15 +0200 Subject: MERGE --- .../Tango.MachineStudio.Stubs/StubManager.cs | 181 +++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Stubs/StubManager.cs (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Stubs/StubManager.cs') diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Stubs/StubManager.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Stubs/StubManager.cs new file mode 100644 index 000000000..8e0eafa3a --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Stubs/StubManager.cs @@ -0,0 +1,181 @@ +using Google.Protobuf; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Tango.PMR; +using Tango.PMR.Common; +using Tango.Stubs; +using Tango.Transport; +using Tango.Transport.Adapters; + +namespace Tango.MachineStudio.Stubs +{ + /// + /// Represents a manager capable of executing stub scripts asynchronously. + /// + public class StubManager + { + private ITransportAdapter _adapter; //Holds the USB transport adapter. + + /// + /// Occurs when the stub has failed to execute. + /// + public event EventHandler Failed; + + /// + /// Occurs when the stub has completed successfully. + /// + public event EventHandler Completed; + + /// + /// Occurs when the stub has been initialized and executed. + /// + public event EventHandler Executed; + + /// + /// Gets a value indicating whether this is aborted. + /// + internal bool Aborted { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The adapter. + public StubManager(ITransportAdapter adapter) + { + _adapter = adapter; + } + + /// + /// Aborts the current script. + /// + internal void Abort() + { + Aborted = true; + } + + /// + /// Runs the specified stub name. + /// + /// Name of the stub. + /// The arguments. + public void Run(String stubName, params Object[] args) + { + if (Aborted) return; + + var stubType = StubBase.GetAvailableRequestStubs().SingleOrDefault(x => x.Name.ToLower() == stubName.ToLower() || x.Name.Replace("Request", "").ToLower() == stubName.ToLower()); + if (stubType == null) + { + OnFailed(new ArgumentException("Invalid stub '" + stubName + "'.")); + return; + } + + var stubProps = stubType.GetProperties(BindingFlags.Public | BindingFlags.Instance); + + if (stubProps.Length > args.Length) + { + OnFailed(new ArgumentOutOfRangeException("Not enough arguments for " + stubType.Name + ".")); + return; + } + + Executed?.Invoke(this, stubType.Name); + + try + { + MessageContainer container = new MessageContainer(); + container.Token = Guid.NewGuid().ToString(); + container.Type = MessageFactory.ParseMessageType(stubType.Name); + + Object request = Activator.CreateInstance(stubType); + + int argIndex = 0; + foreach (var prop in stubProps) + { + String arg = args[argIndex++].ToString(); + + if (prop.PropertyType == typeof(UInt32)) + { + prop.SetValue(request, UInt32.Parse(arg)); + } + else if (prop.PropertyType == typeof(bool)) + { + prop.SetValue(request, bool.Parse(arg)); + } + else + { + object converted = Convert.ChangeType(arg, prop.PropertyType); + prop.SetValue(request, converted); + } + } + + container.Data = typeof(IMessage).GetExtensionMethod(typeof(ByteString).Assembly, "ToByteString").Invoke(request, new object[] { request }) as ByteString; + + byte[] requestData = container.ToByteArray(); + + bool done = false; + + Task.Factory.StartNew(() => + { + _adapter.Write(requestData); + + DateTime startTime = DateTime.Now; + + MessageContainer responseContainer = null; + + _adapter.DataAvailable += (sender, data) => + { + responseContainer = MessageFactory.ParseContainer(data); + }; + + while (responseContainer == null) + { + Thread.Sleep(2); + + if (DateTime.Now > startTime.AddSeconds(2)) + { + done = true; + OnFailed(new TimeoutException("Response has failed to arrive after 2 seconds.")); + return; + } + } + + IMessage message = MessageFactory.ParseMessageFromContainer(responseContainer); + OnCompleted(JsonConvert.SerializeObject(message, Formatting.Indented)); + done = true; + }); + + while (!done) + { + Thread.Sleep(2); + } + } + catch (Exception ex) + { + OnFailed(ex); + } + } + + /// + /// Raises the event. + /// + /// The exception. + protected virtual void OnFailed(Exception ex) + { + Failed?.Invoke(this, ex); + } + + /// + /// Raises the event. + /// + /// The response. + protected virtual void OnCompleted(String response) + { + Completed?.Invoke(this, response); + } + } +} -- cgit v1.3.1