diff options
| author | Roy <roy.mail.net@gmail.com> | 2017-12-26 21:16:15 +0200 |
|---|---|---|
| committer | Roy <roy.mail.net@gmail.com> | 2017-12-26 21:16:15 +0200 |
| commit | 2ea2bb5bcd96045f1bd6cb4c3d8b8416dbaa05dc (patch) | |
| tree | a21ff27fff08876e835df82c5242def1f0d09c17 /Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Stubs/StubManager.cs | |
| parent | 6450fc175114a6f8d0b75cb21386d1bb0c902711 (diff) | |
| download | Tango-2ea2bb5bcd96045f1bd6cb4c3d8b8416dbaa05dc.tar.gz Tango-2ea2bb5bcd96045f1bd6cb4c3d8b8416dbaa05dc.zip | |
MERGE
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Stubs/StubManager.cs')
| -rw-r--r-- | Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Stubs/StubManager.cs | 181 |
1 files changed, 181 insertions, 0 deletions
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 +{ + /// <summary> + /// Represents a manager capable of executing stub scripts asynchronously. + /// </summary> + public class StubManager + { + private ITransportAdapter _adapter; //Holds the USB transport adapter. + + /// <summary> + /// Occurs when the stub has failed to execute. + /// </summary> + public event EventHandler<Exception> Failed; + + /// <summary> + /// Occurs when the stub has completed successfully. + /// </summary> + public event EventHandler<String> Completed; + + /// <summary> + /// Occurs when the stub has been initialized and executed. + /// </summary> + public event EventHandler<String> Executed; + + /// <summary> + /// Gets a value indicating whether this <see cref="StubManager"/> is aborted. + /// </summary> + internal bool Aborted { get; private set; } + + /// <summary> + /// Initializes a new instance of the <see cref="StubManager"/> class. + /// </summary> + /// <param name="adapter">The adapter.</param> + public StubManager(ITransportAdapter adapter) + { + _adapter = adapter; + } + + /// <summary> + /// Aborts the current script. + /// </summary> + internal void Abort() + { + Aborted = true; + } + + /// <summary> + /// Runs the specified stub name. + /// </summary> + /// <param name="stubName">Name of the stub.</param> + /// <param name="args">The arguments.</param> + 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); + } + } + + /// <summary> + /// Raises the <see cref="Failed"/> event. + /// </summary> + /// <param name="ex">The exception.</param> + protected virtual void OnFailed(Exception ex) + { + Failed?.Invoke(this, ex); + } + + /// <summary> + /// Raises the <see cref="Completed"/> event. + /// </summary> + /// <param name="response">The response.</param> + protected virtual void OnCompleted(String response) + { + Completed?.Invoke(this, response); + } + } +} |
