diff --git a/Examples/Program.cs b/Examples/Program.cs index 39fbe84..0575d77 100644 --- a/Examples/Program.cs +++ b/Examples/Program.cs @@ -79,6 +79,14 @@ class Program { //set the current second to the PLCs TIME register interf.SetRegister(nameof(registers.TestTime), TimeSpan.FromSeconds(DateTime.Now.Second)); + while(true) { + + Console.WriteLine($"Speed UP: {interf.BytesPerSecondUpstream} B/s"); + Console.WriteLine($"Speed DOWN: {interf.BytesPerSecondDownstream} B/s"); + + await Task.Delay(1000); + } + }); } diff --git a/MewtocolNet/Mewtocol/DynamicInterface.cs b/MewtocolNet/Mewtocol/DynamicInterface.cs index 7ce2c8a..8f702f7 100644 --- a/MewtocolNet/Mewtocol/DynamicInterface.cs +++ b/MewtocolNet/Mewtocol/DynamicInterface.cs @@ -117,6 +117,8 @@ namespace MewtocolNet { it++; + await Task.Delay(PollerDelayMs); + } }); diff --git a/MewtocolNet/Mewtocol/MewtocolInterface.cs b/MewtocolNet/Mewtocol/MewtocolInterface.cs index 4c54900..4855c68 100644 --- a/MewtocolNet/Mewtocol/MewtocolInterface.cs +++ b/MewtocolNet/Mewtocol/MewtocolInterface.cs @@ -52,6 +52,15 @@ namespace MewtocolNet { set { connectTimeout = value; } } + private int pollerDelayMs = 0; + /// + /// Delay for each poller cycle in milliseconds, default = 0 + /// + public int PollerDelayMs { + get { return pollerDelayMs; } + set { pollerDelayMs = value; } + } + /// /// The host ip endpoint, leave it null to use an automatic interface /// @@ -101,6 +110,9 @@ namespace MewtocolNet { private int stationNumber; private int cycleTimeMs = 25; + private int bytesTotalCountedUpstream = 0; + private int bytesTotalCountedDownstream = 0; + /// /// The current IP of the PLC connection /// @@ -125,6 +137,30 @@ namespace MewtocolNet { } } + private int bytesPerSecondUpstream = 0; + /// + /// The current transmission speed in bytes per second + /// + public int BytesPerSecondUpstream { + get { return bytesPerSecondUpstream; } + private set { + bytesPerSecondUpstream = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(BytesPerSecondUpstream))); + } + } + + private int bytesPerSecondDownstream = 0; + /// + /// The current transmission speed in bytes per second + /// + public int BytesPerSecondDownstream { + get { return bytesPerSecondDownstream; } + private set { + bytesPerSecondDownstream = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(BytesPerSecondDownstream))); + } + } + internal NetworkStream stream; internal TcpClient client; internal readonly SerialQueue queue = new SerialQueue(); @@ -132,6 +168,9 @@ namespace MewtocolNet { internal int SendExceptionsInRow = 0; internal bool ImportantTaskRunning = false; + private Stopwatch speedStopwatchUpstr; + private Stopwatch speedStopwatchDownstr; + #region Initialization /// @@ -736,6 +775,16 @@ namespace MewtocolNet { var message = _blockString.ToHexASCIIBytes(); + //time measuring + if(speedStopwatchUpstr == null) { + speedStopwatchUpstr = Stopwatch.StartNew(); + } + + if(speedStopwatchUpstr.Elapsed.TotalSeconds >= 1) { + speedStopwatchUpstr.Restart(); + bytesTotalCountedUpstream = 0; + } + //send request using (var sendStream = new MemoryStream(message)) { await sendStream.CopyToAsync(stream); @@ -743,6 +792,13 @@ namespace MewtocolNet { Logger.Log($"--> OUT MSG: {_blockString}", LogLevel.Critical, this); } + //calc upstream speed + bytesTotalCountedUpstream += message.Length; + + var perSecUpstream = (double)((bytesTotalCountedUpstream / speedStopwatchUpstr.Elapsed.TotalMilliseconds) * 1000); + if (perSecUpstream <= 10000) + BytesPerSecondUpstream = (int)Math.Round(perSecUpstream, MidpointRounding.AwayFromZero); + //await result StringBuilder response = new StringBuilder(); try { @@ -755,6 +811,17 @@ namespace MewtocolNet { while (!endLineCode && !startMsgCode) { do { + + //time measuring + if (speedStopwatchDownstr == null) { + speedStopwatchDownstr = Stopwatch.StartNew(); + } + + if (speedStopwatchDownstr.Elapsed.TotalSeconds >= 1) { + speedStopwatchDownstr.Restart(); + bytesTotalCountedDownstream = 0; + } + int bytes = await stream.ReadAsync(responseBuffer, 0, responseBuffer.Length); endLineCode = responseBuffer.Any(x => x == 0x0D); @@ -777,8 +844,18 @@ namespace MewtocolNet { } if(!string.IsNullOrEmpty(response.ToString())) { + Logger.Log($"<-- IN MSG: {response}", LogLevel.Critical, this); + + bytesTotalCountedDownstream += Encoding.ASCII.GetByteCount(response.ToString()); + + var perSecDownstream = (double)((bytesTotalCountedDownstream / speedStopwatchDownstr.Elapsed.TotalMilliseconds) * 1000); + + if(perSecUpstream <= 10000) + BytesPerSecondDownstream = (int)Math.Round(perSecUpstream, MidpointRounding.AwayFromZero); + return response.ToString(); + } else { return null; } diff --git a/MewtocolNet/MewtocolNet.csproj b/MewtocolNet/MewtocolNet.csproj index d45388b..b116755 100644 --- a/MewtocolNet/MewtocolNet.csproj +++ b/MewtocolNet/MewtocolNet.csproj @@ -2,7 +2,7 @@ netstandard2.0 MewtocolNet - 0.5.2 + 0.5.5 Felix Weiss Womed true diff --git a/MewtocolNet/Queue/SerialQueue.cs b/MewtocolNet/Queue/SerialQueue.cs index a1faf22..06001bf 100644 --- a/MewtocolNet/Queue/SerialQueue.cs +++ b/MewtocolNet/Queue/SerialQueue.cs @@ -8,47 +8,6 @@ namespace MewtocolNet.Queue { readonly object _locker = new object(); readonly WeakReference _lastTask = new WeakReference(null); - internal Task Enqueue (Action action) { - return Enqueue(() => { - action(); - return true; - }); - } - - internal Task Enqueue (Func function) { - lock (_locker) { - Task lastTask; - Task resultTask; - - if (_lastTask.TryGetTarget(out lastTask)) { - resultTask = lastTask.ContinueWith(_ => function(), TaskContinuationOptions.ExecuteSynchronously); - } else { - resultTask = Task.Run(function); - } - - _lastTask.SetTarget(resultTask); - - return resultTask; - } - } - - internal Task Enqueue (Func asyncAction) { - lock (_locker) { - Task lastTask; - Task resultTask; - - if (_lastTask.TryGetTarget(out lastTask)) { - resultTask = lastTask.ContinueWith(_ => asyncAction(), TaskContinuationOptions.ExecuteSynchronously).Unwrap(); - } else { - resultTask = Task.Run(asyncAction); - } - - _lastTask.SetTarget(resultTask); - - return resultTask; - } - } - internal Task Enqueue (Func> asyncFunction) { lock (_locker) { Task lastTask;