From 63b2a192ba12f8239668b6818db4ad02db68dbbc Mon Sep 17 00:00:00 2001 From: Roy Date: Wed, 3 Jan 2018 01:57:58 +0200 Subject: Implemented abstraction of message encoding/decoding by adding another layer of "Encoders" to Transporters. --- .../Services/ExternalBridgeClient.cs | 2 +- Software/Visual_Studio/Tango.PMR/ITangoMessage.cs | 34 ++++++++++++ Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj | 1 + Software/Visual_Studio/Tango.PMR/TangoMessage.cs | 10 ++-- .../Tango.Transport/Encoders/ProtoEncoder.cs | 47 +++++++++++++++++ .../Tango.Transport/ITransportAdapter.cs | 10 ++++ .../Tango.Transport/ITransportEncoder.cs | 37 +++++++++++++ .../Visual_Studio/Tango.Transport/ITransporter.cs | 5 ++ .../Tango.Transport/Tango.Transport.csproj | 5 +- .../Tango.Transport/TransportAdapterBase.cs | 31 ++++++++++- .../Tango.Transport/TransporterBase.cs | 61 +++++----------------- .../Transporters/BasicTransporter.cs | 47 +++++++++++++++++ .../Transporters/JsonTransporter.cs | 60 --------------------- .../Transporters/ProtoTransporter.cs | 47 ----------------- .../Tango.MachineEM.UI/ViewModels/MainViewVM.cs | 2 +- .../Utilities/Tango.MobileEM.UI/App.xaml.cs | 2 +- 16 files changed, 235 insertions(+), 166 deletions(-) create mode 100644 Software/Visual_Studio/Tango.PMR/ITangoMessage.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Encoders/ProtoEncoder.cs create mode 100644 Software/Visual_Studio/Tango.Transport/ITransportEncoder.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Transporters/BasicTransporter.cs delete mode 100644 Software/Visual_Studio/Tango.Transport/Transporters/JsonTransporter.cs delete mode 100644 Software/Visual_Studio/Tango.Transport/Transporters/ProtoTransporter.cs (limited to 'Software/Visual_Studio') diff --git a/Software/Visual_Studio/Tango.Integration/Services/ExternalBridgeClient.cs b/Software/Visual_Studio/Tango.Integration/Services/ExternalBridgeClient.cs index b783ec261..aec9c0db0 100644 --- a/Software/Visual_Studio/Tango.Integration/Services/ExternalBridgeClient.cs +++ b/Software/Visual_Studio/Tango.Integration/Services/ExternalBridgeClient.cs @@ -12,7 +12,7 @@ using Tango.Transport.Transporters; namespace Tango.Integration.Services { - public class ExternalBridgeClient : ProtoTransporter, IExternalBridgeClient + public class ExternalBridgeClient : BasicTransporter, IExternalBridgeClient { private String _serialNumber; diff --git a/Software/Visual_Studio/Tango.PMR/ITangoMessage.cs b/Software/Visual_Studio/Tango.PMR/ITangoMessage.cs new file mode 100644 index 000000000..90b33a6bb --- /dev/null +++ b/Software/Visual_Studio/Tango.PMR/ITangoMessage.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.PMR.Common; + +namespace Tango.PMR +{ + public interface ITangoMessage + { + /// + /// Gets the container that will encapsulate the actual PMR message. + /// + MessageContainer Container { get; } + + /// + /// Gets or sets the PMR message type. + /// + MessageType Type { get; set; } + + /// + /// Serializes the Tango message to byte array. + /// + /// + byte[] ToBytes(); + + /// + /// Serializes the Tango message to byte array representing a serialized JSON object of this Tango message. + /// + /// + byte[] ToJsonBytes(); + } +} diff --git a/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj b/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj index 7226685ea..e3846da7a 100644 --- a/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj +++ b/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj @@ -55,6 +55,7 @@ + diff --git a/Software/Visual_Studio/Tango.PMR/TangoMessage.cs b/Software/Visual_Studio/Tango.PMR/TangoMessage.cs index 4819ac509..c99fc0dfb 100644 --- a/Software/Visual_Studio/Tango.PMR/TangoMessage.cs +++ b/Software/Visual_Studio/Tango.PMR/TangoMessage.cs @@ -13,10 +13,10 @@ namespace Tango.PMR /// Represents a wrapper class for PRM messages. /// /// - public class TangoMessage where T : IMessage + public class TangoMessage : ITangoMessage where T : IMessage { /// - /// Gets the container. + /// Gets the container that will encapsulate the actual PMR message. /// public MessageContainer Container { get; } @@ -26,7 +26,7 @@ namespace Tango.PMR public T Message { get; set; } /// - /// Gets or sets the message type. + /// Gets or sets the PMR message type. /// public MessageType Type { get; set; } @@ -46,7 +46,7 @@ namespace Tango.PMR } /// - /// Generates a new containing the message of type and returns a byte array. + /// Serializes the Tango message to byte array. /// /// public byte[] ToBytes() @@ -61,7 +61,7 @@ namespace Tango.PMR } /// - /// Generates a new containing the message of type and returns a byte array. + /// Serializes the Tango message to byte array representing a serialized JSON object of this Tango message. /// /// public byte[] ToJsonBytes() diff --git a/Software/Visual_Studio/Tango.Transport/Encoders/ProtoEncoder.cs b/Software/Visual_Studio/Tango.Transport/Encoders/ProtoEncoder.cs new file mode 100644 index 000000000..689b331e6 --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Encoders/ProtoEncoder.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.PMR; +using Tango.PMR.Common; + +namespace Tango.Transport.Encoders +{ + /// + /// Represents a protobuf Transport Encoder. + /// + /// + public class ProtoEncoder : ITransportEncoder + { + /// + /// Decodes the specified data. + /// + /// The data. + /// + public ITangoMessage Decode(byte[] data) + { + return MessageFactory.ParseTangoMessageAgnostic(data) as ITangoMessage; + } + + /// + /// Decodes only the container part of the message. + /// + /// The data. + /// + public MessageContainer DecodeContainer(byte[] data) + { + return MessageFactory.ParseContainer(data); + } + + /// + /// Encodes the specified tango message. + /// + /// The tango message. + /// + public byte[] Encode(ITangoMessage tangoMessage) + { + return tangoMessage.ToBytes(); + } + } +} diff --git a/Software/Visual_Studio/Tango.Transport/ITransportAdapter.cs b/Software/Visual_Studio/Tango.Transport/ITransportAdapter.cs index 5ab48e503..413ea7559 100644 --- a/Software/Visual_Studio/Tango.Transport/ITransportAdapter.cs +++ b/Software/Visual_Studio/Tango.Transport/ITransportAdapter.cs @@ -14,6 +14,16 @@ namespace Tango.Transport /// public interface ITransportAdapter : ITransportComponent { + /// + /// Gets the total bytes received. + /// + long TotalBytesReceived { get; } + + /// + /// Gets the total bytes sent. + /// + long TotalBytesSent { get; } + /// /// Writes the specified data to the stream. /// diff --git a/Software/Visual_Studio/Tango.Transport/ITransportEncoder.cs b/Software/Visual_Studio/Tango.Transport/ITransportEncoder.cs new file mode 100644 index 000000000..beae60d14 --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/ITransportEncoder.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.PMR; +using Tango.PMR.Common; + +namespace Tango.Transport +{ + /// + /// Represents a Transport message encoder capable of encoding or decoding Tango Messages. + /// + public interface ITransportEncoder + { + /// + /// Encodes the specified tango message. + /// + /// The tango message. + /// + byte[] Encode(ITangoMessage tangoMessage); + + /// + /// Decodes the specified data. + /// + /// The data. + /// + ITangoMessage Decode(byte[] data); + + /// + /// Decodes only the container part of the message. + /// + /// The data. + /// + MessageContainer DecodeContainer(byte[] data); + } +} diff --git a/Software/Visual_Studio/Tango.Transport/ITransporter.cs b/Software/Visual_Studio/Tango.Transport/ITransporter.cs index 9d6f13446..0c06e68f8 100644 --- a/Software/Visual_Studio/Tango.Transport/ITransporter.cs +++ b/Software/Visual_Studio/Tango.Transport/ITransporter.cs @@ -24,6 +24,11 @@ namespace Tango.Transport /// ITransportAdapter Adapter { get; set; } + /// + /// Gets or sets the transport encoder used to encode and decode tango messages. + /// + ITransportEncoder Encoder { get; set; } + /// /// Sends a request. /// diff --git a/Software/Visual_Studio/Tango.Transport/Tango.Transport.csproj b/Software/Visual_Studio/Tango.Transport/Tango.Transport.csproj index aa5b5ef67..88e2a3b75 100644 --- a/Software/Visual_Studio/Tango.Transport/Tango.Transport.csproj +++ b/Software/Visual_Studio/Tango.Transport/Tango.Transport.csproj @@ -66,9 +66,11 @@ GlobalVersionInfo.cs + + @@ -81,8 +83,7 @@ - - + diff --git a/Software/Visual_Studio/Tango.Transport/TransportAdapterBase.cs b/Software/Visual_Studio/Tango.Transport/TransportAdapterBase.cs index 100990d0e..b996c82b2 100644 --- a/Software/Visual_Studio/Tango.Transport/TransportAdapterBase.cs +++ b/Software/Visual_Studio/Tango.Transport/TransportAdapterBase.cs @@ -31,6 +31,26 @@ namespace Tango.Transport #region Properties + private long _totalBytesReceived; + /// + /// Gets the total bytes received. + /// + public long TotalBytesReceived + { + get { return _totalBytesReceived; } + protected set { _totalBytesReceived = value; } + } + + private long _totalBytesSent; + /// + /// Gets the total bytes sent. + /// + public long TotalBytesSent + { + get { return _totalBytesSent; } + protected set { _totalBytesSent = value; } + } + /// /// Gets or sets the channel address. /// @@ -76,6 +96,7 @@ namespace Tango.Transport /// The data. protected virtual void OnDataAvailable(byte[] data) { + TotalBytesReceived += data.Length; DataAvailable?.Invoke(this, data); } @@ -106,14 +127,20 @@ namespace Tango.Transport /// protected virtual byte[] PostProcessBuffer(byte[] data) { + byte[] postData = data; + if (AdapterMode == TransportAdapterMode.NO_HEADER) { - return data; + return postData; } else { - return BitConverter.GetBytes(data.Length).Concat(data).ToArray(); + postData = BitConverter.GetBytes(data.Length).Concat(data).ToArray(); } + + TotalBytesSent += postData.Length; + + return postData; } #endregion diff --git a/Software/Visual_Studio/Tango.Transport/TransporterBase.cs b/Software/Visual_Studio/Tango.Transport/TransporterBase.cs index 756738ee8..2e25d5bf1 100644 --- a/Software/Visual_Studio/Tango.Transport/TransporterBase.cs +++ b/Software/Visual_Studio/Tango.Transport/TransporterBase.cs @@ -14,6 +14,7 @@ using Tango.PMR; using Tango.PMR.Common; using System.Reactive.Linq; using System.ServiceModel; +using Tango.Transport.Encoders; namespace Tango.Transport { @@ -57,6 +58,11 @@ namespace Tango.Transport set { _adapter = value; OnAdapterChanged(value); } } + /// + /// Gets or sets the transport encoder used to encode and decode tango messages. + /// + public ITransportEncoder Encoder { get; set; } + private TransportComponentState _state; /// /// Gets the component state. @@ -103,6 +109,7 @@ namespace Tango.Transport /// public bool FailsWithAdapter { get; set; } + #endregion #region Virtual Methods @@ -183,47 +190,6 @@ namespace Tango.Transport StateChanged?.Invoke(this, state); } - /// - /// Override in order to provide a method serializer for . - /// - /// The type of the request. - /// The message. - /// - protected virtual Func OnSerializeingMessage(TangoMessage message) where Request : IMessage - { - return message.ToBytes; - } - - /// - /// Override in order to provide a deserialized message container part of the message. - /// - /// The data. - /// - protected virtual MessageContainer OnParseContainer(byte[] data) - { - return MessageFactory.ParseContainer(data); - } - - /// - /// Override in order to provide a deserialized message from a container. - /// - /// The container. - /// - protected virtual IMessage OnParseMessage(MessageContainer container) - { - return MessageFactory.ParseMessageFromContainer(container); - } - - /// - /// Called when [parse tango message]. - /// - /// The bytes. - /// - protected virtual Object OnParseTangoMessage(byte[] bytes) - { - return MessageFactory.ParseTangoMessageAgnostic(bytes); - } - #endregion #region Constructors @@ -233,6 +199,7 @@ namespace Tango.Transport /// public TransporterBase() { + Encoder = new ProtoEncoder(); _pendingResponses = new Dictionary(); _sendingQueue = new ConcurrentQueue(); _pendingRequests = new List(); @@ -297,7 +264,7 @@ namespace Tango.Transport LogManager.Log("Expected response: " + typeof(Response).Name); TaskCompletionSource> source = new TaskCompletionSource>(); - TransportMessage> message = new TransportMessage>(request.Container.Token, request, TransportMessageDirection.Request, OnSerializeingMessage(request), source); + TransportMessage> message = new TransportMessage>(request.Container.Token, request, TransportMessageDirection.Request, () => Encoder.Encode(request), source); _sendingQueue.Enqueue(message); Task.Delay(timeout != null ? timeout.Value : RequestTimeout).ContinueWith((x) => { @@ -329,7 +296,7 @@ namespace Tango.Transport request.Container.Continuous = true; request.Container.Completed = false; - TransportMessage> message = new TransportMessage>(request.Container.Token, request, TransportMessageDirection.Request, OnSerializeingMessage(request), null) + TransportMessage> message = new TransportMessage>(request.Container.Token, request, TransportMessageDirection.Request, () => Encoder.Encode(request), null) { IsContinuous = true, ContinuesResponseSubject = subject, @@ -389,7 +356,7 @@ namespace Tango.Transport } TaskCompletionSource source = new TaskCompletionSource(); - TransportMessage message = new TransportMessage(token, response, TransportMessageDirection.Response, OnSerializeingMessage(response), source); + TransportMessage message = new TransportMessage(token, response, TransportMessageDirection.Response, () => Encoder.Encode(response), source); _sendingQueue.Enqueue(message); return source.Task; } @@ -492,7 +459,7 @@ namespace Tango.Transport LogManager.Log("Message received on adapter: " + Adapter.Address); LogManager.Log("Parsing message container..."); - MessageContainer container = OnParseContainer(data); + MessageContainer container = Encoder.DecodeContainer(data); LogManager.Log("Searching for pending request token: " + container.Token); TransportMessageBase request = _pendingRequests.SingleOrDefault(x => x.Token == container.Token); @@ -511,7 +478,7 @@ namespace Tango.Transport if (container.Error == ErrorCode.None) { LogManager.Log("Parsing inner response message and setting pending request task result..."); - request.SetResult(OnParseTangoMessage(data), true); + request.SetResult(Encoder.Decode(data), true); LogManager.Log("Message enquirer released..."); } else @@ -538,7 +505,7 @@ namespace Tango.Transport { LogManager.Log("Continuous sequence completed."); } - request.SetResult(OnParseTangoMessage(data), container.Completed); + request.SetResult(Encoder.Decode(data), container.Completed); } else { diff --git a/Software/Visual_Studio/Tango.Transport/Transporters/BasicTransporter.cs b/Software/Visual_Studio/Tango.Transport/Transporters/BasicTransporter.cs new file mode 100644 index 000000000..06c1f3921 --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Transporters/BasicTransporter.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; +using System.Text; +using System.Threading.Tasks; +using Google.Protobuf; +using Tango.Transport.Adapters; +using Tango.PMR; +using Tango.PMR.Common; +using System.Collections.Concurrent; +using System.Reactive.Subjects; +using System.Threading; +using System.Reactive; +using System.Reactive.Disposables; +using Tango.Logging; + +namespace Tango.Transport.Transporters +{ + /// + /// Represents an which send and receive messages using Protobuf binary data. + /// + /// + public class BasicTransporter : TransporterBase + { + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + public BasicTransporter() : base() + { + + } + + /// + /// Initializes a new instance of the class. + /// + /// The transport adapter. + public BasicTransporter(ITransportAdapter adapter) : base(adapter) + { + + } + + #endregion + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Transporters/JsonTransporter.cs b/Software/Visual_Studio/Tango.Transport/Transporters/JsonTransporter.cs deleted file mode 100644 index d490d4a61..000000000 --- a/Software/Visual_Studio/Tango.Transport/Transporters/JsonTransporter.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Google.Protobuf; -using Tango.PMR; -using Tango.PMR.Common; - -namespace Tango.Transport.Transporters -{ - /// - /// Represents an which send and receive messages using JSON formatted strings. - /// - /// - public class JsonTransporter : TransporterBase - { - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - public JsonTransporter() : base() - { - - } - - /// - /// Initializes a new instance of the class. - /// - /// The transport adapter. - public JsonTransporter(ITransportAdapter adapter) : base(adapter) - { - - } - - #endregion - - /// - /// Override in order to provide a method serializer for . - /// - /// The type of the request. - /// The message. - /// - protected override Func OnSerializeingMessage(TangoMessage message) - { - return message.ToJsonBytes; - } - - /// - /// Override in order to provide a deserialized message container part of the message. - /// - /// The data. - /// - protected override MessageContainer OnParseContainer(byte[] data) - { - return MessageFactory.ParseContainerJson(data); - } - } -} diff --git a/Software/Visual_Studio/Tango.Transport/Transporters/ProtoTransporter.cs b/Software/Visual_Studio/Tango.Transport/Transporters/ProtoTransporter.cs deleted file mode 100644 index 7c82639d2..000000000 --- a/Software/Visual_Studio/Tango.Transport/Transporters/ProtoTransporter.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reactive.Linq; -using System.Text; -using System.Threading.Tasks; -using Google.Protobuf; -using Tango.Transport.Adapters; -using Tango.PMR; -using Tango.PMR.Common; -using System.Collections.Concurrent; -using System.Reactive.Subjects; -using System.Threading; -using System.Reactive; -using System.Reactive.Disposables; -using Tango.Logging; - -namespace Tango.Transport.Transporters -{ - /// - /// Represents an which send and receive messages using Protobuf binary data. - /// - /// - public class ProtoTransporter : TransporterBase - { - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - public ProtoTransporter() : base() - { - - } - - /// - /// Initializes a new instance of the class. - /// - /// The transport adapter. - public ProtoTransporter(ITransportAdapter adapter) : base(adapter) - { - - } - - #endregion - } -} diff --git a/Software/Visual_Studio/Utilities/Tango.MachineEM.UI/ViewModels/MainViewVM.cs b/Software/Visual_Studio/Utilities/Tango.MachineEM.UI/ViewModels/MainViewVM.cs index ad5c449c8..0ffc89fdf 100644 --- a/Software/Visual_Studio/Utilities/Tango.MachineEM.UI/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/Utilities/Tango.MachineEM.UI/ViewModels/MainViewVM.cs @@ -153,7 +153,7 @@ namespace Tango.MachineEM.UI.ViewModels LogManager.RegisterLogger(logger); - Emulator = new MachineEmulator(new ProtoTransporter()); + Emulator = new MachineEmulator(new BasicTransporter()); StartCommand = new RelayCommand(Start, (x) => !Emulator.IsStarted); StopCommand = new RelayCommand(Stop,(x) => Emulator.IsStarted); diff --git a/Software/Visual_Studio/Utilities/Tango.MobileEM.UI/App.xaml.cs b/Software/Visual_Studio/Utilities/Tango.MobileEM.UI/App.xaml.cs index 306da384f..36c360c5a 100644 --- a/Software/Visual_Studio/Utilities/Tango.MobileEM.UI/App.xaml.cs +++ b/Software/Visual_Studio/Utilities/Tango.MobileEM.UI/App.xaml.cs @@ -21,7 +21,7 @@ namespace Tango.MobileEM.UI protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); - Emulator = new MobileEmulator(new ProtoTransporter(new UsbTransportAdapter("COM2"))); + Emulator = new MobileEmulator(new BasicTransporter(new UsbTransportAdapter("COM2"))); } } } -- cgit v1.3.1