aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Stubs/StubManager.cs
diff options
context:
space:
mode:
authorRoy <roy.mail.net@gmail.com>2017-12-26 21:16:15 +0200
committerRoy <roy.mail.net@gmail.com>2017-12-26 21:16:15 +0200
commit2ea2bb5bcd96045f1bd6cb4c3d8b8416dbaa05dc (patch)
treea21ff27fff08876e835df82c5242def1f0d09c17 /Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Stubs/StubManager.cs
parent6450fc175114a6f8d0b75cb21386d1bb0c902711 (diff)
downloadTango-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.cs181
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);
+ }
+ }
+}